在PowerShell中,我需要更改系统路径变量:
$oldPath = [System.Environment]::GetEnvironmentVariable('Path', 'Machine')
[System.Environment]::SetEnvironmentVariable('Path', (Transform-It $oldPath), 'Machine')
然后启动一个程序:
& $someExeName 'someargument'
我得到的问题是可执行文件正在使用旧环境。它无法识别新路径。如果我还更改$env.path
,要仅更改此PowerShell会话的路径,它也不会传播到新进程。如果我关闭PowerShell并在新窗口中启动可执行文件,那很好。据推测,它继承了PowerShell流程中的(未更新的)环境。
在PowerShell中更改环境变量并通过从该窗口启动的新进程识别它的最佳实践是什么?
通常,子进程从父进程*继承环境。如果从现有PowerShell会话生成新的PowerShell会话,则新会话将从该会话继承环境变量(但不包含其他变量)。
但是,Path变量是一个导致很多混淆的异常:即使它是一个环境变量,新的PowerShell会话也会从注册表项HKLM:\System\CurrentControlSet\Control\Session Manager\Environment
读取其值,从而覆盖从父会话继承的值。
start powershell
),则新会话将具有来自注册表的路径,但如果您生成cmd会话,则新会话将具有产生它的PowerShell会话的路径。
»同样,如果在cmd会话中更改Path(使用set Path=New Path
)并生成PowerShell会话,则新会话将具有来自注册表的路径,但是如果您生成cmd会话,则它将具有来自父cmd的更改路径会话。
»默认行为是从父进程继承路径(以及环境的其余部分)(如cmd所示)。但是,很有可能其他一些程序的行为与PowerShell类似,用注册表值覆盖继承的值。这种行为并不常见,但不能排除可执行文件发生这种情况的可能性。以下命令更改当前会话中的路径,而不是在注册表中:
$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会话中的路径,以及您正在生成的可执行文件两种方式都没有改变的路径。 AFAIK原始环境不会缓存在任何地方,子进程必须从父进程的环境或注册表获取路径。
我建议您确保在启动可执行文件之前已经双向改变了路径:
如果由于某些无法解释的原因不起作用,请尝试以下方法:
powershell "& $someExeName 'someargument'"
使用可从注册表中读取Path环境变量的新但非交互式PowerShell会话启动可执行文件。*请注意,环境的继承是Windows中父进程和子进程之间的唯一关系。除此之外,它们完全独立(没有像Unix和Linux那样的层次结构)。