Skip to content

Commit

Permalink
(GH-728) Fix: Env var changes may require reboot
Browse files Browse the repository at this point in the history
Setting environment variables directly in the registry has a side
effect of sometimes not letting explorer.exe know that something
changed. When that happens, it doesn't matter if you open a new shell
or not, the environment variables available to new shells will reflect
the older values.

The fix for this is a two fold attack - broadcast the change and set
another environment variable with SetX.

Broadcasting the change using the native method
`SendMessageTimeout` has no effect on currently open shells, but helps
GUIs and explorer.exe realize that something changed and that they
should look to refresh their environment values.

SetX.exe also has no effect on the current shell, but it forces
explorer.exe to refresh the values that are available. Set a user
environment variable with the current date and time.  This also has a
nice side effect of letting the user know the last time the environment
was updated by Chocolatey.

If either of these fail, report the error as a warning.
  • Loading branch information
ferventcoder committed May 9, 2016
1 parent 0fdfd4d commit a238223
Showing 1 changed file with 28 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,33 @@ function Set-EnvironmentVariable([string] $Name, [string] $Value, [System.Enviro

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

try {
# make everything refresh
# because sometimes explorer.exe just doesn't get the message that things were updated.
if (-not ("win32.nativemethods" -as [type])) {
# import sendmessagetimeout from win32
add-type -Namespace Win32 -Name NativeMethods -MemberDefinition @"
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam,
uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
"@
}

$HWND_BROADCAST = [intptr]0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [uintptr]::zero

# notify all windows of environment block change
[win32.nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [uintptr]::Zero, "Environment", 2, 5000, [ref]$result) | Out-Null

# Set a user environment variable making the system refresh
$setx = "$($env:SystemRoot)\System32\setx.exe"
& "$setx" ChocolateyLastPathUpdate `"$(Get-Date -UFormat %c)`" | Out-Null

} catch {
Write-Warning "Failure attempting to let Explorer know about updated environment settings.`n $($_.Exception.Message)"
}

Update-SessionEnvironment
}

0 comments on commit a238223

Please sign in to comment.