Skip to content

Instantly share code, notes, and snippets.

@Iristyle
Last active February 25, 2016 14:51
Show Gist options
  • Save Iristyle/9a870f96f1896710c01f to your computer and use it in GitHub Desktop.
Save Iristyle/9a870f96f1896710c01f to your computer and use it in GitHub Desktop.
Reset environment variables
# initial stash of process vars that will overwrite Machine / User vars
if (! $processVars)
{
# capture all variables by name, using whats currently available in-proc for values (already expanded)
$processVars = [Environment]::GetEnvironmentVariables('Process').Keys |
% -Begin { $h = @{} } -Process { $h.$_ = (Get-Item Env:\$_).Value } -End { $h }
# Write-Host "Initially captured process vars:`n`n$($processVars | Out-String)"
# eliminate Machine / User vars so that we have only process vars
'Machine', 'User' |
% { [Environment]::GetEnvironmentVariables($_).GetEnumerator() } |
? { $processVars.ContainsKey($_.Name) -and ($processVars[$_.Name] -eq $_.Value) } |
% { $processVars.Remove($_.Name) }
# Write-Host "Stored process vars:`n`n$($processVars | Out-String)"
}
# query Machine vars from registry, ensuring expansion EXCEPT for PATH
$vars = [Environment]::GetEnvironmentVariables('Machine').GetEnumerator() |
% -Begin { $h = @{} } -Process { $v = if ($_.Name -eq 'Path') { $_.Value } else { [Environment]::GetEnvironmentVariable($_.Name, 'Machine') }; $h."$($_.Name)" = $v } -End { $h }
# Write-Host "Read MACHINE vars:`n`n$($vars | Out-String)"
# query User vars from registry, ensuring expansion EXCEPT for PATH
[Environment]::GetEnvironmentVariables('User').GetEnumerator() |
% {
if ($_.Name -eq 'Path') { $vars[$_.Name] += ';' + $_.Value }
else
{
$value = [Environment]::GetEnvironmentVariable($_.Name, 'User')
$vars[$_.Name] = $value
# Write-Host "Re-read $($_.Name) from User as $value / stored as $($vars[$_.Name])"
}
}
# Write-Host "Vars updated with USER vars:`n`n$($vars | Out-String)"
$processVars.GetEnumerator() | % { $vars[$_.Name] = $_.Value }
# Write-Host "Vars updated with Process vars:`n`n$($vars | Out-String)"
Remove-Item Env:\*
$vars.GetEnumerator() |
% { Set-Item -Path "Env:\$($_.Name)" -Value $_.Value }
@Iristyle
Copy link
Author

One interesting thing to note is that the restored environment has unexpanded environment variables (which is OK / expected for PATH), but might be a problem in ComSpec and windir - so there might need to be special handling there. Calling GetEnvironmentVariable will expand, while GetEnvironmentVariables does not expand.

I have modified the code so that everything is captured / reinstated verbatim, including observing existing behavior around which variables are expanded, etc.

@ferventcoder
Copy link

https://gist.github.com/Iristyle/9a870f96f1896710c01f#file-env-reset-ps1-L11

Note, this is going to destroy $env:PSMODULEPATH. We would need to skip this one.

@ferventcoder
Copy link

Oh sweet, capturing the Process variables 👍

@jpogran
Copy link

jpogran commented Feb 24, 2016

After line 40 $processVars has 26 items, wheres (ls env:).Count has 38. The variables missing cripple the shell to the point where the process crashes. Still figuring out what is missing here

$vars has the full process list, but still the process crashes after line 44

@jpogran
Copy link

jpogran commented Feb 25, 2016

The fix, strangely enough, was to sort the $processVars by Name before attempting to pass it to the next block. This originates from passing the results of the inner PS session $processVars to the outer PS session, then back into the inner PS session later on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment