繁体   English   中英

使用PowerShell设置嵌套的可扩展环境变量

[英]Set nested expandable environment variable with PowerShell

我已经阅读了很多关于这个主题的帖子,并尝试了很多东西,但似乎无法让这个工作。 我想设置一个环境变量,然后将该变量嵌套在Path环境变量中。 我从批处理文件切换到Powershell,因为我无法进行后期扩展工作以防止扩展路径中已有的嵌套变量等。

这是用于演示该问题的脚本。 鉴于您已将Maven解压缩到e:\\Apps\\maven\\apache-maven-3.2.1位置,测试脚本将运行,创建MAVEN_HOME变量,在路径中嵌套该未变量的变量,并执行mvn --help

这一切都很好,除了打开一个新的命令提示符并键入ECHO %PATH% ,很明显没有应用更改。

我听说环境变量的字母顺序很重要,但在这种情况下,“MAVEN_HOME”出现在“PATH”之前,所以这无关紧要。

Path变量在注册表中以REG_EXPAND_SZ类型创建。

我正在从批处理文件运行Powershell脚本以避免签名:

Call Powershell.exe -executionpolicy bypass -File .\test.ps1

这是Powershell脚本:

#Environment Variable
$HOME_VAR = "MAVEN_HOME"
$HOME_PATH = "e:\Apps\maven\apache-maven-3.2.1"
$APP_CMD = "mvn"
$APP_ARGS = "--help"

#String to be added to the Path
$BIN_PATH = "%$HOME_VAR%\bin"

#Registry location of Machine Environment variables
$SYSVAR_REG_PATH = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"

#Get the correct hive
$HKLM = [Microsoft.Win32.Registry]::LocalMachine
#Get the registry key with true to indicate that it is for editing
$sysvar_regkey = $HKLM.OpenSubKey($SYSVAR_REG_PATH, $TRUE)

#Set the value in the registry
$sysvar_regkey.SetValue($HOME_VAR, $HOME_PATH)

#Read the value back out
$HOME_PATH = $sysvar_regkey.GetValue($HOME_VAR)

#Set the value within the current process
[Environment]::SetEnvironmentVariable($HOME_VAR, $HOME_PATH, [EnvironmentVariableTarget]::Process)

#Must use RegistryKey to get value because it allows the "DoNotExpandEnvironmentNames" option
#This ensures that nested environment variables are not expanded when read
$envpath = $sysvar_regkey.GetValue("Path", "C:\Windows", [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
$segments = $envpath.split(";")

Write-Host "BEFORE"
Write-Host $env:path

#See if bin path is already in the Path
If (($segments -contains $BIN_PATH) -eq $FALSE) {
    #Add the bin path to the path
    $segments += $BIN_PATH
    $envpath = $segments -join ";"

    #RegistryValueKind.ExpandString ensures that variables in the path will expand when the Path is read
    $sysvar_regkey.SetValue("Path", $envpath, [Microsoft.Win32.RegistryValueKind]::ExpandString)
}   

#Read the path value as expanded
#All nested variables in the Path are expanded
$envpath = $sysvar_regkey.GetValue("Path")

#Update the Path for the current process
#Must do this every time to expand the Path
[Environment]::SetEnvironmentVariable("Path", $envpath, [EnvironmentVariableTarget]::Process)

Write-Host "AFTER"
Write-Host $env:path

#Run the command line
& $APP_CMD $APP_ARGS | Write-Host

新的cmd会话使用从父进程的环境继承的路径(通常是Windows资源管理器,或者生成它的cmd或PowerShell会话)。 更改注册表中环境变量的值不会自动更改Explorer的环境,因此它不会更改新cmd会话使用的值。

如果通过“ 系统属性”控制面板设置环境变量,则该值将反映在新的cmd会话中,而不是因为它存储在注册表中,而是因为它还会更改主Explorer进程环境中的值。 (请注意,只需从“ 系统属性”中打开“ 环境变量”对话框,然后单击“ 确定”即可从注册表值更新所有Explorer的环境变量)。

要从PowerShell获得相同的效果 - 同时更改注册表中的值以及在传递给新cmd会话的资源管理器环境中 - 您可以执行以下操作:

[Environment]::SetEnvironmentVariable("Path", $envpath, 'Machine')

请注意,这并不能取代

[Environment]::SetEnvironmentVariable("Path", $envpath, 'Process')

因为如果目标是Machine ,则不会更改当前PowerShell会话中的值。 (您可以使用字符串'Process''Machine'代替[EnvironmentVariableTarget]::Process[EnvironmentVariableTarget]::Machine )。


请注意,BTW,新的PowerShell会话始终使用注册表中的Path值而不是从父级继承的值。 此行为仅适用于Path ; 所有其他环境变量都从父进程继承。 有关更多信息,请参阅此答案

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM