I do a thing to install JDK when a Windows virtual machine boot, use a cloudinit user-data to transfer a PowerShell script to the windows machine, and run the script to install JDK.
$softwares = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*
$jdk = $softwares | Where-Object DisplayName -match 'Java SE Development Kit'
$java_home = $jdk.InstallLocation.Trim('\')
#$java_home = "C:\Program Files\Java\jdk1.7.0_80"
$classpath = ".;%JAVA_HOME%\lib;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar"
$path = ";%JAVA_HOME%\bin;" + $env:Path
[Environment]::SetEnvironmentVariable("JAVA_HOME", $java_home, "machine")
[Environment]::SetEnvironmentVariable("CLASSPATH", $classpath, "machine")
[Environment]::SetEnvironmentVariable("PATH", $path , "machine")
The problem is my script installs the JDK successfully and modifies the environment variables correctly, but the command java still doesn't run. The path is right and the path in the registry is right,too.
I am sure the path is right because when I modify "Path" (delete ',' in the head of "Path") by steps such as MyPC/RigthClick/Properties/Advaced/EnvironmentVariables/. And I also try to configure "Path" without ";" in the head, still can't run java successfully, modify "Path" by add ";", it runs well.
解决方案
Environment variables are stored in the registry. [Environment]::SetEnvironmentVariable() writes the given variable as a REG_SZ value, but for nested variables to be expanded you need a REG_EXPAND_SZ value.
If you want to use %JAVA_HOME%\bin in the PATH use Set-ItemProperty instead of [Environment]::SetEnvironmentVariable():
$regkey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
Set-ItemProperty -Path $regkey -Name 'Path' -Value $path -Type ExpandString
Beware that there may be other pitfalls when using nested variables in environment variables due to the order in which they're expanded. Raymond Chen described the behavior in the article Windows Confidential: The hidden variables.