簡體   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