如何通过命令行在Windows中确定地修改PATH变量

10

我想创建一个 .bat 文件,可以在 Windows PATH 变量的值末尾添加一些字符串。需要注意的是,我希望这个更改是永久性的,而不仅仅对当前会话有效。

有人知道如何实现吗?尽可能地,它不应该依赖于 Windows 的版本。

2个回答

24

很抱歉回答这么长,但是你的问题无法简短回答。

首先你需要理解环境变量是如何工作的。在注册表中有像 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\EnvironmentHKEY_CURRENT_USER\Environment 这样的位置来保存环境变量。操作系统在启动时读取这些注册表键值。然后一个Windows进程创建另一个Windows进程。父进程可以给客户端进程任何一组环境变量。如果父进程不这样做,子进程将继承父进程的环境变量。

要能够更新正在运行的进程的环境变量,可以使用 WM_WININICHANGEWM_SETTINGCHANGE 消息。Windows应用程序可以解释这些消息,并从注册表中的 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\EnvironmentHKEY_CURRENT_USER\Environment 重新读取当前的环境变量。因此,你通常可以更改 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\EnvironmentHKEY_CURRENT_USER\Environment 下的注册表值并发送

SendMessage (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment");
使用SendMessageTimeout比使用SendMessage更好,但想法保持不变。问题在于其他进程不能等待该消息并执行操作。大多数控制台应用程序没有消息循环,如果您发送这样的消息,它们将不执行任何操作。

因此,重要的是要了解,在不重新启动计算机的情况下,没有简单的方法可以更新所有进程的环境变量。您应该清楚地理解这一点,并缩小问题的范围。

如果您在注册表中更新环境并发送SendMessage (HWND_BROADCAST, WM_SETTINGCHANGE, 0, (LPARAM)"Environment"),则由Explorer.exe创建的新进程将具有新的环境变量,但cmd.exe不会这样做。

如果您想在批处理运行中更新当前cmd.exe的环境变量,可以执行以下操作:在%TEMP%目录中创建一个名为t.cmd的新CMD文件,写入SET PATH=%PATH%;C:\BlaBla,然后使用call %TEMP%\t.cmddell %TEMP%\t.cmd来更新当前cmd.exe的环境变量。

确切地说,还有更多用于构建新创建进程的环境变量的位置。这些是键HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths的子键和%SystemRoot%\System32\autoexec.nt文件。其中一个将用于由ShellExecuteShellExecuteEx(例如Explorer.exe)创建的进程,另一个将用于控制台应用程序。


2
哇,非常感谢您提供如此详细的答案。我相信这对其他人也会很有价值。 话虽如此,当我想到在Linux中做这样的事情是多么容易时,我有点失望。 - madewulf

4
如果你只关心新的流程实例,并且你真的想通过批处理文件完成它,那么 setx 就是你要找的东西。
  • /M 会在 HKEY_LOCAL_MACHINE 中更改 PATH,而不是在 HKEY_CURRENT_USER 中更改。
    即系统变量,而不是用户的变量。
    例如:SETX /M PATH "%PATH%;C:\your path with spaces"
如果你想直接为当前运行的进程更改环境变量,那么是很复杂的,显然不推荐
Altering the environment variables of a child process during process creation 
is the only way one process can directly change the environment variables of 
another process. A process can never directly change the environment variables 
of another process that is not a child of that process.

否则,就像Oleg所说的那样,以编程方式最好的方法是更改注册表并发送WM_SETTINGCHANGE,希望应用程序足够友好地接受它。

1
太好了,这正是我在寻找的!仅供记录:1) /M 在设置 PATH 时会设置系统变量而不是新用户变量。语法:SETX /M PATH "%PATH%;C:\your path with spaces" 2) 缺点是:PATH 中的所有系统变量都将被解析,例如 %SystemRoot%(将变为 C:\Windows),尽管我认为这并没有错。 - Qwerty

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接