我不明白这一点。因此,目前我的系统环境变量“PSModulePath”如下所示:
%ProgramFiles%\WindowsPowerShell\Modules;%SystemRoot%\system32\WindowsPowerShell\v1.0\Modules
现在观察以下 PowerShell 脚本:
$envarname = "PSModulePath"
$envar = (get-item env:$envarname).Value
[Environment]::SetEnvironmentVariable($envarname, $envar + ";C:\Expedited", "Machine")
全部应该要做的就是将路径“C:\Expedited”添加到 PSModulesPath 环境变量中,对吗?那么,以管理员身份运行此脚本后,PSModulePath 环境变量将变为:
C:\Users\Username\Documents\WindowsPowerShell\Modules;C:\Program Files\WindowsPowerShell\Modules;C:\Windows\system32\WindowsPowerShell\v1.0\Modules;C:\Expedited
注意:
- 原本有两条路径,原来每条路径都含有百分号(变量),后来都直接变成了硬编码路径。
- “C:\Users\Username\Documents\WindowsPowerShell\Modules”路径突然出现(原来没有这个路径!)
我不知道为什么会发生这两件事。当向此变量添加路径时,我希望它尽可能接近原始路径,而不是进行所有这些其他更改。有什么方法可以保留丢失的百分号吗? 如何在 PowerShell 中正确编辑此环境变量?
答案1
PowerShell - 无需扩展即可获取操作系统环境变量
您可以使用获取项目cmdlet 带有-path
参数,然后传递包含环境变量的注册表项的路径PSModulePath
。
然后您可以使用RegistryKey.GetValue 方法随着 不要扩展环境名称获取PSModulePath
环境变量的字符串值而不扩展它。
电源外壳
$envarname = "PSModulePath"
$regkey = Get-Item -Path "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
$envar = $regkey.GetValue($envarname, "", "DoNotExpandEnvironmentNames")
ECHO $envar
笔记:您需要确保从管理员提升的 PowerShell 命令提示符或 ISE 屏幕运行它,以使其正常工作。
更多资源
操作方法:在 Windows 中设置环境变量 - 命令行和注册表
用户变量在注册表中的位置是:
HKEY_CURRENT_USER\Environment
。系统变量在注册表中的位置是:HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
通过注册表设置环境变量时,它们不会立即被识别。一种选择是注销并重新登录。但是,如果我们发送 WM_SETTINGCHANGE 消息,当以编程方式执行此操作时,这只是另一行,但是如果在命令行上执行此操作,则并不那么简单。
-
检索与指定名称和检索选项关联的值。如果未找到该名称,则返回您提供的默认值。
RegistryKey.GetValue 方法(字符串、对象、RegistryValueOptions)
使用此重载指定对检索到的值进行特殊处理。例如,您可以指定 RegistryValueOptions.DoNotExpandEnvironmentNames 检索 RegistryValueKind.ExpandString 类型的注册表值时,检索字符串而不扩展嵌入的环境变量。
答案2
您正在执行一些对于您的最终目标来说并非真正必要的额外步骤。只需使用 MS 指南中所示的默认步骤即可。
因此,根据以上文章,您只需要最后一个例子,或者只需要一行,通过使用内置的默认/自动环境变量。
[System.Environment]::SetEnvironmentVariable("PSModulePath", $Env:PSModulePath + ";C:\Expedited","Machine")
答案3
其他答案已经解决了环境变量扩展问题,但为什么“ C:\Users\Username\Documents\WindowsPowerShell\Modules
”会突然出现:
PSModulePath 是一个棘手的问题。它不能充当其他环境变量。
在 Powershell 之外,与任何其他环境变量一样,如果它同时存在于用户和机器的环境中,则机器的环境中的变量将被丢弃。
但在 Powershell 中,PSModulePath 是一个串联:用户路径 + 计算机路径。(有点像“路径”,但有趣的是,“路径”的工作原理相反:先计算机,然后是用户)。
默认计算机 PSModulePath 为“ %ProgramFiles%\WindowsPowerShell\Modules;%SystemRoot%\system32\windowspowershell\v1.0\Modules
”。如果您定义的计算机 PSModulePath 不包含这两个路径,Powershell 会自动添加它们。
(之所以有两条路径,是因为 中的模块%SystemRoot%
与 32 位和 64 位版本的 Powershell 兼容,而 中的模块%ProgramFiles%
则不兼容(诀窍在于%ProgramFiles%
将 32 位版本解析为“Program Files (x86)”)。)
用户也有一个默认的 PSModulePath,它是%USERDOC%\WindowsPowerShell\Modules
。但如果它充当机器对应物,那就太简单了:如果未定义用户 PSModulePath,则在 Powershell 中,其值设置为%USERDOC%\WindowsPowerShell\Modules
,这就是你的“它突然出现”。
现在,如果为用户定义了 PSModulePath,则其值就是定义的值,而%USERDOC%\WindowsPowerShell\Modules
不会被添加。
我不知道我说得是否清楚。但是我最近被 PSModule 问题困扰,而且似乎在任何地方都找不到该技术信息。
(最后说明:我不会给出细节,但我在这里写的所有内容仅对 Windos Powershell(v5)有效。Powershell7 添加了新的路径。)