更新至$env:EnvVarName
影响仅当前进程- 不会通过注册表进行持久性更改:
$env:EnvVarName = 'foo'
相当于调用.NET方法System.Environment.SetEnvironmentVariable如下:
[Environment]::SetEnvironmentVariable('EnvVarName', 'foo', 'Process')
也就是说,更新的范围是当前进程.
Only if you substitute 'User'
or 'Machine'
for 'Process'
in the above call (supported on Windows only[1]) do you persistently update environment variables in the registry (for the current user or the local machine (all users), respectively), for future sessions (processes)[2].
As of PowerShell [Core] 7.2, there is no PowerShell-native way to persistently update environment variables, but introducing one is being discussed on GitHub.
换句话说:如果您不仅想更新基于注册表的定义,还想更新当前进程中的值,则需要both calls;例如,对于当前用户:
# Windows only: Update / create a persistent definition for the current user,
# stored in the registry.
[Environment]::SetEnvironmentVariable('EnvVarName', 'foo', 'User')
# Update value for current process too.
$env:EnvVarName = 'foo'
或者,更多的是本着DRY:
'User', 'Process' | foreach {
[Environment]::SetEnvironmentVariable('EnvVarName', 'foo', $_)
}
如果新值基于给定注册表范围中的现有值,请通过以下方式检索特定于范围的值:System.Environment.GetEnvironmentVariable; e.g.:
# Get the registry-based *user* value
[Environment]::GetEnvironmentVariable('Path', 'User')
警告:不支持基于 Windows 的环境变量REG_EXPAND_SZ
注册表值:
在 Windows 上,持久定义的环境变量可以基于other环境变量,即定义该变量的基础注册表值是否属于类型REG_EXPAND_SZ
.
从 .NET 6 开始,System.Environmenttype 的方法做not(直接)支持这样的环境变量:
悄悄转变的同时REG_EXPAND_SZ
环境变量改为静态REG_SZ
那些通常可能没有不良影响(只要新值仅包含文字值),它当然can:例如,假设一个变量是根据以下形式定义的%JAVADIR%
;如果该变量根据当时的当前值转换为静态值%JAVADIR%
,如果值为%JAVADIR%
是后来改变的。
很遗憾,检索原始数据REG_EXPAND_SZ
目前需要环境变量及其值的正确更新直接注册表访问,这相当麻烦(甚至 Windows API 似乎也不支持它) - 请参阅这个答案.
重要考虑因素Path
环境变量($env:PATH
) 在 Windows 上:
重要的: The Path
Windows 上的环境变量是REG_EXPAND_SZ
默认情况下基于 -,因此需要注意安静地转换为静态REG_SZ
以下代码执行的基于值的应用 - 再次参见这个答案寻求适当但更复杂的解决方案。
Example:
# New dir. to add to the *user's* path
$newDir = 'c:\foo\bin'
# Get current value *from the registry*
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
# Append the new dir and save back to the registry.
[Environment]::SetEnvironmentVariable('Path', ($userPath + ';' + $newDir), 'User')
# To also update the current process, append $newDir to the in-process
# variable, $env:Path
$env:Path += ';' + $newDir
顺便说一句:开类 Unix 平台,分隔符是:
, not ;
(体现[System.IO.Path]::PathSeparator
,以及区分大小写变量名称是Path
。如前所述,.NET 基本上不提供执着的类 Unix 平台上的环境变量定义(从 .NET Core 3.1 开始),因为各个平台没有统一的本机机制来执行此操作。
[1] On Unix-like platforms, targeting User
or Machine
is quietly ignored as of .NET Core 3.1
[2] Caveat: New processes created directly by the current PowerShell session (direct invocation, Start-Process
, Start-Job
) do not yet see the registry changes, because the inherit the current session's environment.