-
Notifications
You must be signed in to change notification settings - Fork 78
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Notify processes to refresh their environment variables #1657
Notify processes to refresh their environment variables #1657
Conversation
Hi! Thank you very much for taking this on!
(EDIT: Thank you Misty for taking over!) |
Ah, I bet that comes down to the |
Currently only for the powershell installer
76bd390
to
478aaba
Compare
I've pushed an update with snapshots and a couple minor tweaks:
|
@fdcastel makes a good point in #1614 (comment) that I do think should be considered before merging I thought for sure
The main thing that strikes me as odd is why this hasn't been recommended by any online resources that I found! It does seem "more official" than this approach though. At the very bottom in "Applies to" it looks like it does support quite old .Net https://learn.microsoft.com/en-us/dotnet/api/system.environment.setenvironmentvariable?view=net-9.0 |
@DavisVaughan, absolutely! As a Windows user and programmer for, err... longer than I care to admit, I can vouch for this method being old. But it works😉. That said, it is practically a newborn compared to those ancient Win32 messages -- which predates even the .NET framework itself! (being there, done that...) 😄 |
Whew, okay, holy cow. Windows powershell is SUCH a minefield with anything I have determined that there are a few issues, all related to the fact that for The issue with
|
$OldPath = $Item | Get-ItemPropertyValue -Name $PropertyName |
i.e. from the above example %EXPANDME%
would be expanded into my\path
as we retrieved it, then we'd hardcode it back to my\path
as we "set" the Path
, meaning if I update EXPANDME
in the future then my Path
won't respond to the change anymore. I believe it has already permanently expanded my %NVM_HOME%
and %NVM_SYMLINK%
variables 😬.
Here is a way to avoid expansion:
$Item = Get-Item -LiteralPath 'registry::HKEY_CURRENT_USER\Environment'
$Item.GetValue('Path', '', 'DoNotExpandEnvironmentNames')
The current use of New-ItemProperty
is forcing a REG_SZ
type
Note -PropertyType String
. That causes the Path
to get stored as REG_SZ
, which is the same problem as SetEnvironmentVariable()
. Luckily, if we use -PropertyType ExpandString
then it will correctly get stored as REG_EXPAND_SZ
.
Worth noting that rustup is careful to also use ExpandString
when resetting the PATH
right before sending out the broadcast message:
- https://github.com/rust-lang/rustup/blob/dc9d072c34eccbee2d9249daea177b9c4263c5da/src/cli/self_update/windows.rs#L483
- https://github.com/microsoft/windows-rs/blob/ad8d166e070484066ccccf9754af64f7415025d8/crates/libs/registry/src/key.rs#L113-L119
You can see this issue in this screen shot which was taken after using the current version of the installer. See how everything else is REG_EXPAND_SZ
?
Is there no hope?
There is an excellent post all about this here:
https://stackoverflow.com/questions/69236623/adding-path-permanently-to-windows-using-powershell-doesnt-appear-to-work/69239861#69239861
It includes an Add-Path
helper that solves all of these problems and more:
- It uses
GetValue('Path', '', 'DoNotExpandEnvironmentNames')
when retrieving the currentPath
- It uses
-Type ExpandString
when creating/updating thePath
- It broadcasts
WM_SETTINGCHANGE
by utilizing[Environment]::SetEnvironmentVariable()
to create and then immediately remove a dummy environment variable, which has the side effect of sending outWM_SETTINGCHANGE
. Pretty clever I think. And uses the "officially exposed" API to broadcast that message. - It even updates the current
Path
by modifying$env:Path
before it exits, so you don't even technically have to restart your shell (we could remove this part if it makes us uncomfortable)
Closes #1614
This currently only handles the powershell installer, not msi. If someone wants to add and test msi support that would be great! Also, can someone please take over updating snapshot tests for me? I tried but got weird diffs like this:
And a few other failures I couldn't figure out.
The opening post here #1614 (comment) discusses the problem in detail.
I opted to bring in the (well known?) implementation from the powershell gallery
https://www.powershellgallery.com/packages/PSCI/1.0.4/Content/core%5Cutils%5CUpdate-EnvironmentVariables.ps1
I tested this on a Windows machine and this does indeed seem to work for me! Here's a video of me showing that
.local/
in the registryhttps://vimeo.com/1040789276?share=copy#t=0
@fdcastel noted that it did not work for him. I believe I can explain that. Likely what happened was:
Running
Get-Item -Path "HKCU:\Environment"
would likely show an updatedPath
for him, even thoughruff
won't be accessible at the command line until after a system restart.