Skip to content

Commit

Permalink
(GH-699) Fix: PATH may break on Install-ChocolateyPath
Browse files Browse the repository at this point in the history
The fixes for GH-303 (e050c22) had an interesting and terrible side
effect. When you don't expand the value and then you update using
`[Environment]::SetEnvironmentVariable($Name, $Value, $Scope)`, it has
the side effect of overwriting the original registry value type and
saves the values as `REG_SZ` instead of keeping it as `REG_EXPAND_SZ`.
Then all of the tools in WinDir no longer work all of a sudden and
it's somewhat perplexing what happened as everything looks appropriate
when you inspect the values.

You can verify if you are affected by opening a new command line and
typing `where.exe choco` and the system cannot find where.exe, which is
at `C:\Windows\System32\where.exe`.

You are only affected if you installed (explicitly installed, not upgraded)
one of the following beta releases directly:

 * https://chocolatey.org/packages/chocolatey/0.9.10-beta-20160411
 * https://chocolatey.org/packages/chocolatey/0.9.10-beta-20160422
 * https://chocolatey.org/packages/chocolatey/0.9.10-beta-20160503

This is fixed by attempting to ask the registry what the value type is
for the particular key and falling back to `REG_SZ` when it is not
found. Environment variables are always either String or ExpandString. As
a further step, if it is the `PATH` variable, it will always be saved as
ExpandString (`REG_EXPAND_SZ`).

Then set the value using `[Microsoft.Win32.Registry]::SetValue` instead
because it allows setting the value type.
  • Loading branch information
ferventcoder committed May 5, 2016
1 parent a356f4c commit c3d4ff3
Showing 1 changed file with 28 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,32 @@

function Set-EnvironmentVariable([string] $Name, [string] $Value, [System.EnvironmentVariableTarget] $Scope) {
Write-Debug "Calling Set-EnvironmentVariable with `$Name = '$Name', `$Value = '$Value', `$Scope = '$Scope'"
[Environment]::SetEnvironmentVariable($Name, $Value, $Scope)

if ($Scope -eq [System.EnvironmentVariableTarget]::Process) {
return [Environment]::SetEnvironmentVariable($Name, $Value, $Scope)
}

[string]$keyHive = 'HKEY_LOCAL_MACHINE'
[string]$registryKey = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment\"
[Microsoft.Win32.RegistryKey] $win32RegistryKey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey($registryKey)
if ($Scope -eq [System.EnvironmentVariableTarget]::User) {
$keyHive = 'HKEY_CURRENT_USER'
$registryKey = "Environment"
[Microsoft.Win32.RegistryKey] $win32RegistryKey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey($registryKey)
}

[Microsoft.Win32.RegistryValueKind]$registryType = [Microsoft.Win32.RegistryValueKind]::String
try {
$registryType = $reg.GetValueKind($Name)
} catch {
# the value doesn't yet exist
# move along, nothing to see here
}
Write-Debug "Registry type for $Name is/will be $registryType"

if ($Name -eq 'PATH') {
$registryType = [Microsoft.Win32.RegistryValueKind]::ExpandString
}

[Microsoft.Win32.Registry]::SetValue($keyHive + "\" + $registryKey, $Name, $Value, $registryType)
}

0 comments on commit c3d4ff3

Please sign in to comment.