如何从C ++更改Windows shell(cmd.exe)环境变量?

时间:2021-05-23 22:58:49

I would like to write a program that sets an environment variable in an instance of the shell (cmd.exe) it was called from. The idea is that I could store some state in this variable and then use it again on a subsequent call.

我想编写一个程序,在调用它的shell(cmd.exe)实例中设置一个环境变量。我的想法是我可以在这个变量中存储一些状态,然后在后续调用中再次使用它。

I know there are commands like SetEnvironmentVariable, but my understanding is that those only change the variable for the current process and won't modify the calling shell's variables.

我知道有像SetEnvironmentVariable这样的命令,但我的理解是那些只改变当前进程的变量而不会修改调用shell的变量。

Specifically what I would like to be able to do is create a command that can bounce between two directories. Pushd/Popd can go to a directory and back, but don't have a way of returning a 2nd time to the originally pushed directory.

具体来说,我希望能够创建一个可以在两个目录之间跳转的命令。 Pushd / Popd可以转到目录并返回,但是没有办法将第二次返回到最初推送的目录。

4 个解决方案

#1


A common techniques is the write an env file, that is then "call"ed from the script.

一种常见的技术是编写一个env文件,然后从脚本中“调用”ed。

del env.var
foo.exe ## writes to env.var
call env.var

#2


MSDN states the following:

MSDN声明如下:

Calling SetEnvironmentVariable has no effect on the system environment variables. To programmatically add or modify system environment variables, add them to the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment registry key, then broadcast a WM_SETTINGCHANGE message with lParam set to the string "Environment". This allows applications, such as the shell, to pick up your updates. Note that the values of the environment variables listed in this key are limited to 1024 characters.

调用SetEnvironmentVariable对系统环境变量没有影响。以编程方式添加或修改系统环境变量,把它们添加到HKEY_LOCAL_MACHINE \系统\ CurrentControlSet \控制\会话管理\环境的注册表项,然后广播WM_SETTINGCHANGE消息的lParam设置为字符串“环境”。这允许应用程序(如shell)获取更新。请注意,此键中列出的环境变量的值限制为1024个字符。

Considering that there are two levels of environment - System and Process - changing those in the shell would constitute changing the environment of another process. I don't believe that this is possible.

考虑到有两个级别的环境 - 系统和流程 - 更改shell中的那些将构成改变另一个流程的环境。我不相信这是可能的。

#3


In Windows when one process creates another, it can simply let the child inherit the current environment strings, or it can give the new child process a modified, or even completely new environment.

在Windows中,当一个进程创建另一个进程时,它可以简单地让子进程继承当前的环境字符串,或者它可以为新的子进程提供修改的甚至是全新的环境。

See the full info for the CreateProccess() win32 API

查看CreateProccess()win32 API的完整信息

There is no supported way for a child process to reach back to the parent process and change the parent's environment.

子进程没有受支持的方式来回到父进程并更改父进程的环境。

That being said, with CMD scripts and PowerShell, the parent command shell can take output from the child process and update its own environment. This is a common technique.

话虽这么说,使用CMD脚本和PowerShell,父命令shell可以从子进程获取输出并更新其自己的环境。这是一种常见的技术。

personly, I don't like any kind of complex CMD scripts - they are a bitch to write an debug. You may want to do this in PowerShell - there is a learning curve to be sure, but it is much richer.

我不喜欢任何复杂的CMD脚本 - 他们是编写调试的婊子。您可能希望在PowerShell中执行此操作 - 确保学习曲线,但它更丰富。

#4


There is a way... Just inject your code into parent process and call SetEnvironmentVariableA inside cmd's process memory. After injecting just free the allocated memory.

有一种方法......只需将代码注入父进程并在cmd的进程内存中调用SetEnvironmentVariableA即可。注入后只需释放分配的内存。

#1


A common techniques is the write an env file, that is then "call"ed from the script.

一种常见的技术是编写一个env文件,然后从脚本中“调用”ed。

del env.var
foo.exe ## writes to env.var
call env.var

#2


MSDN states the following:

MSDN声明如下:

Calling SetEnvironmentVariable has no effect on the system environment variables. To programmatically add or modify system environment variables, add them to the HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment registry key, then broadcast a WM_SETTINGCHANGE message with lParam set to the string "Environment". This allows applications, such as the shell, to pick up your updates. Note that the values of the environment variables listed in this key are limited to 1024 characters.

调用SetEnvironmentVariable对系统环境变量没有影响。以编程方式添加或修改系统环境变量,把它们添加到HKEY_LOCAL_MACHINE \系统\ CurrentControlSet \控制\会话管理\环境的注册表项,然后广播WM_SETTINGCHANGE消息的lParam设置为字符串“环境”。这允许应用程序(如shell)获取更新。请注意,此键中列出的环境变量的值限制为1024个字符。

Considering that there are two levels of environment - System and Process - changing those in the shell would constitute changing the environment of another process. I don't believe that this is possible.

考虑到有两个级别的环境 - 系统和流程 - 更改shell中的那些将构成改变另一个流程的环境。我不相信这是可能的。

#3


In Windows when one process creates another, it can simply let the child inherit the current environment strings, or it can give the new child process a modified, or even completely new environment.

在Windows中,当一个进程创建另一个进程时,它可以简单地让子进程继承当前的环境字符串,或者它可以为新的子进程提供修改的甚至是全新的环境。

See the full info for the CreateProccess() win32 API

查看CreateProccess()win32 API的完整信息

There is no supported way for a child process to reach back to the parent process and change the parent's environment.

子进程没有受支持的方式来回到父进程并更改父进程的环境。

That being said, with CMD scripts and PowerShell, the parent command shell can take output from the child process and update its own environment. This is a common technique.

话虽这么说,使用CMD脚本和PowerShell,父命令shell可以从子进程获取输出并更新其自己的环境。这是一种常见的技术。

personly, I don't like any kind of complex CMD scripts - they are a bitch to write an debug. You may want to do this in PowerShell - there is a learning curve to be sure, but it is much richer.

我不喜欢任何复杂的CMD脚本 - 他们是编写调试的婊子。您可能希望在PowerShell中执行此操作 - 确保学习曲线,但它更丰富。

#4


There is a way... Just inject your code into parent process and call SetEnvironmentVariableA inside cmd's process memory. After injecting just free the allocated memory.

有一种方法......只需将代码注入父进程并在cmd的进程内存中调用SetEnvironmentVariableA即可。注入后只需释放分配的内存。