通常情况下,子进程会继承父进程的环境变量*。如果你从一个已存在的PowerShell会话中创建一个新的PowerShell会话,新会话将继承该会话的环境变量(但不包括其他变量)。
但是,Path变量是一个特例,它经常引起混淆:虽然它是一个环境变量,但新的PowerShell会话会从注册表键HKLM:\System\CurrentControlSet\Control\Session Manager\Environment
读取其值,覆盖从父会话继承的值。
这种行为只适用于Path变量。其他环境变量不受影响,无论它们是在父会话中定义还是存储在前述注册表键中。
此行为也仅适用于PowerShell。
» 如果你在PowerShell会话中更改了Path,但没有在注册表中更改,并且创建了一个新的PowerShell会话(例如使用start powershell
),则新会话将具有来自注册表的路径,但如果你创建了一个cmd会话,则新会话将具有从创建它的PowerShell会话继承的路径。
» 同样地,如果你在cmd会话中更改了Path(使用set Path=New Path
),并创建一个PowerShell会话,则新会话将具有来自注册表的路径,但如果你创建一个cmd会话,则它将具有父cmd会话中更改后的路径。
» 默认行为是从父进程继承路径(以及环境变量的其余部分)(与cmd一样)。但是,很可能有其他程序的行为类似于PowerShell,用注册表值覆盖继承的值。这种行为不常见,但不能排除这种情况发生在你的可执行文件上。
以下命令将在当前会话中更改Path,而不在注册表中更改:
$env:Path = 'New path'
[System.Environment]::SetEnvironmentVariable('Path', 'New Path', 'Process')
以下命令将更改注册表中的
Path,而不是当前会话:
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Session Manager\Environment' -Name 'Path' -Value 'New Path'
[System.Environment]::SetEnvironmentVariable('Path', 'New Path', 'Machine')
你所描述的对我来说没有意义,因为你说你尝试了一种方法改变注册表中的路径,另一种方法改变PowerShell会话中的路径,并且无论哪种方式,你产生的可执行文件都没有更改过的路径。据我所知,原始环境没有被缓存到任何地方,子进程必须从父进程的环境或注册表中获取路径。我的建议是,在启动可执行文件之前务必确保已经通过两种方式都更改了路径:
- 打开一个PowerShell会话
- 使用其中一种在会话中更改路径的方法更改路径
- 使用其中一种在注册表中更改路径的方法更改路径
- 启动可执行文件
如果出现某些莫名其妙的原因导致这不起作用,请尝试以下操作:
- 打开一个PowerShell会话
- 使用其中一种在注册表中更改路径的方法更改路径
而不是直接从该PowerShell会话启动可执行文件,执行此命令:
powershell "& $someExeName 'someargument'"
通过一个新的非交互式PowerShell会话启动可执行文件,该会话将从注册表中读取 Path 环境变量。
*请注意,在Windows中,环境的继承是父子进程之间唯一的关系。除此之外,它们完全独立(与Unix和Linux不同,没有层次结构)。
X=Y launch-process
一样为单个命令设置环境变量? - CMCDragonkai