I have read many posts on this topic and tried many things but cannot seem to get this to work. I want to set an environment variable and then nest that variable in the Path environment variable. I switched from Batch files to Powershell because I could not get late expansion working to prevent expanding nested variables already in the Path, etc.
Here is script to demonstrate the issue. Given that you have Maven unzipped to e:\Apps\maven\apache-maven-3.2.1
location, the test script will run, create the MAVEN_HOME variable, nest that variable unexpanded in the Path, and execute the mvn --help
.
This all works fine, except that upon opening a fresh command prompt and typing ECHO %PATH%
it is clear that the change has not been applied.
I have heard that alphabetical order of the environment variables can matter, but in this case "MAVEN_HOME" comes before "PATH" so that shouldn't matter.
The Path variable is being created in the registry as a REG_EXPAND_SZ
type.
I am running the Powershell script from a batch file to avoid signing:
Call Powershell.exe -executionpolicy bypass -File .\test.ps1
Here is the Powershell script:
#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