ChatGPT解决这个技术问题 Extra ChatGPT

Reload the path in PowerShell

If I have an instance of PowerShell ISE running and I install something that modifies the PATH or I modify it in any way outside of PowerShell then I need to restart PowerShell for it to see the updated PATH variable.

Is there a way to reload the path from within PowerShell without restarting it?


C
Community

Just to bring Rob's comment to light:

$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") 

If you're using chocolatey, and it's loaded into your profile, there's a simpler command: refreshenv. This basically runs a more elaborate version of rob's comment.
if you are installing chocolatey itself and other apps via chocolatey on the same script which modifies the PATH variable, the refreshenv won't work. The refreshenv only works on subseqent shells opened.
The problem with chocolatery is you can't use it in enterprises, it could help a lot with application automated install and when I search for help I encountered non-native solutions like this...
@FrankFu, what if I change path in system Environment Variables in GUI? I think that when installing by choco it ALWAYS changes the path by default. So it is always the same script..
@Timo sorry buddy. I'm not sure what you mean. Do you have an example?
S
Shay Levy

Try getting the machine path and assigning it to the session's path.

$env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine")

Thanks that worked! I also had a user environment variable named path so I had to do this: [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User")
The path changes are more probably in the "User" than in the "Machine" environmental variables.
P
Peter Mortensen

Easiest way, use Chocolatey (freeware). It works for both CMD and PowerShell. Then you will be able to reload PATH (with variable expansion) with a simple command:

refreshenv

Installation from cmd (requires administrator rights):

@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"

Example usage:

> SET JAVA_HOME=c:/java/jdk6
> SET PATH=%JAVA_HOME%/bin
> ECHO %PATH%
c:/java/jdk6/bin

> SET JAVA_HOME=c:/java/jdk8
> refreshenv
Refreshing environment variables from registry for cmd.exe. Please wait...Finished..
> echo %PATH%
c:/java/jdk8/bin

refreshenv didn't work for me (Windows 10). I still had to open a new window for it to take effect.
I tested and use it exactly on Windows 10, it is useful to me quite often. The usage example I've made is not prepared, it's print from my console. Perhaps in your case it's come kind of conflict between user and system variables? Also, as I've noticed, in multiconsole env (like Conemu) it affects current console only.
refreshenv also not working here. Working on some scripts in a Windows Sandbox environment and the path just refuses to updated unless a new PS session is started.
refreshenv only works for cmd in my case, doesn't seem to do anything with powershell
P
Peter Mortensen

If your path contains environment variables that weren't defined at the start of the session, you'll want to expand those too:

$env:Path = [System.Environment]::ExpandEnvironmentVariables([System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User"))

For me this was useful after installing NVM which defines and adds %NVM_HOME% to the path.

To take this to its logical conclusion you could use this recursive function to expand instead:

function Expand-EnvironmentVariablesRecursively($unexpanded) {
    $previous = ''
    $expanded = $unexpanded
    while($previous -ne $expanded) {
        $previous = $expanded
        $expanded = [System.Environment]::ExpandEnvironmentVariables($previous)
    }
    return $expanded
}

And then use:

$env:Path = Expand-EnvironmentVariablesRecursively([System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User"))

I've opened an issue to add this solution into refreshenv from Chocolatey.


P
Peter Mortensen

Based on mpen's answer, here is a PowerShell function:

function refresh-path {
    $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") +
                ";" +
                [System.Environment]::GetEnvironmentVariable("Path","User")
}

Then just call refresh-path.


H
Hashbrown

Just to add to other answers, you can make sure you don't add superfluous joins by filtering in case the user has an empty path.

$env:Path=(
    [System.Environment]::GetEnvironmentVariable("Path","Machine"),
    [System.Environment]::GetEnvironmentVariable("Path","User")
) -match '.' -join ';'

Or, more usefully, if you're running a script that adds to a different or multiple environment variables, use a function to reset them all

function resetEnv {
    Set-Item `
        -Path (('Env:', $args[0]) -join '') `
        -Value ((
            [System.Environment]::GetEnvironmentVariable($args[0], "Machine"),
            [System.Environment]::GetEnvironmentVariable($args[0], "User")
        ) -match '.' -join ';')
}
resetEnv Path
resetEnv AppPath