Setting Windows PowerShell environment variables

前端 未结 18 1761
日久生厌
日久生厌 2020-11-22 11:03

I have found out that setting the PATH environment variable affects only the old command prompt. PowerShell seems to have different environment settings. How do I change the

相关标签:
18条回答
  • 2020-11-22 11:17

    Open PowerShell and run:

    [Environment]::SetEnvironmentVariable("PATH", "$ENV:PATH;<path to exe>", "USER")
    
    0 讨论(0)
  • 2020-11-22 11:19

    From the PowerShell prompt:

    setx PATH "$env:path;\the\directory\to\add" -m
    

    You should then see the text:

    SUCCESS: Specified value was saved.
    

    Restart your session, and the variable will be available. setx can also be used to set arbitrary variables. Type setx /? at the prompt for documentation.

    Before messing with your path in this way, make sure that you save a copy of your existing path by doing $env:path >> a.out in a PowerShell prompt.

    0 讨论(0)
  • 2020-11-22 11:19

    As Jonathan Leaders mentioned here, it is important to run the command/script elevated to be able to change environment variables for 'machine', but running some commands elevated doesn't have to be done with the Community Extensions, so I'd like to modify and extend JeanT's answer in a way, that changing machine variables also can be performed even if the script itself isn't run elevated:

    function Set-Path ([string]$newPath, [bool]$permanent=$false, [bool]$forMachine=$false )
    {
        $Env:Path += ";$newPath"
    
        $scope = if ($forMachine) { 'Machine' } else { 'User' }
    
        if ($permanent)
        {
            $command = "[Environment]::SetEnvironmentVariable('PATH', $env:Path, $scope)"
            Start-Process -FilePath powershell.exe -ArgumentList "-noprofile -command $Command" -Verb runas
        }
    
    }
    
    0 讨论(0)
  • 2020-11-22 11:21

    Like JeanT's answer, I wanted an abstraction around adding to the path. Unlike JeanT's answer I needed it to run without user interaction. Other behavior I was looking for:

    • Updates $env:Path so the change takes effect in the current session
    • Persists the environment variable change for future sessions
    • Doesn't add a duplicate path when the same path already exists

    In case it's useful, here it is:

    function Add-EnvPath {
        param(
            [Parameter(Mandatory=$true)]
            [string] $Path,
    
            [ValidateSet('Machine', 'User', 'Session')]
            [string] $Container = 'Session'
        )
    
        if ($Container -ne 'Session') {
            $containerMapping = @{
                Machine = [EnvironmentVariableTarget]::Machine
                User = [EnvironmentVariableTarget]::User
            }
            $containerType = $containerMapping[$Container]
    
            $persistedPaths = [Environment]::GetEnvironmentVariable('Path', $containerType) -split ';'
            if ($persistedPaths -notcontains $Path) {
                $persistedPaths = $persistedPaths + $Path | where { $_ }
                [Environment]::SetEnvironmentVariable('Path', $persistedPaths -join ';', $containerType)
            }
        }
    
        $envPaths = $env:Path -split ';'
        if ($envPaths -notcontains $Path) {
            $envPaths = $envPaths + $Path | where { $_ }
            $env:Path = $envPaths -join ';'
        }
    }
    

    Check out my gist for the corresponding Remove-EnvPath function.

    0 讨论(0)
  • 2020-11-22 11:21

    All the answers suggesting a permanent change have the same problem: They break the path registry value.

    SetEnvironmentVariable turns the REG_EXPAND_SZ value %SystemRoot%\system32 into a REG_SZ value of C:\Windows\system32.

    Any other variables in the path are lost as well. Adding new ones using %myNewPath% won't work any more.

    Here's a script Set-PathVariable.ps1 that I use to address this problem:

     [CmdletBinding(SupportsShouldProcess=$true)]
     param(
         [parameter(Mandatory=$true)]
         [string]$NewLocation)
    
     Begin
     {
    
     #requires –runasadministrator
    
         $regPath = "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"
         $hklm = [Microsoft.Win32.Registry]::LocalMachine
    
         Function GetOldPath()
         {
             $regKey = $hklm.OpenSubKey($regPath, $FALSE)
             $envpath = $regKey.GetValue("Path", "", [Microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames)
             return $envPath
         }
     }
    
     Process
     {
         # Win32API error codes
         $ERROR_SUCCESS = 0
         $ERROR_DUP_NAME = 34
         $ERROR_INVALID_DATA = 13
    
         $NewLocation = $NewLocation.Trim();
    
         If ($NewLocation -eq "" -or $NewLocation -eq $null)
         {
             Exit $ERROR_INVALID_DATA
         }
    
         [string]$oldPath = GetOldPath
         Write-Verbose "Old Path: $oldPath"
    
         # Check whether the new location is already in the path
         $parts = $oldPath.split(";")
         If ($parts -contains $NewLocation)
         {
             Write-Warning "The new location is already in the path"
             Exit $ERROR_DUP_NAME
         }
    
         # Build the new path, make sure we don't have double semicolons
         $newPath = $oldPath + ";" + $NewLocation
         $newPath = $newPath -replace ";;",""
    
         if ($pscmdlet.ShouldProcess("%Path%", "Add $NewLocation")){
    
             # Add to the current session
             $env:path += ";$NewLocation"
    
             # Save into registry
             $regKey = $hklm.OpenSubKey($regPath, $True)
             $regKey.SetValue("Path", $newPath, [Microsoft.Win32.RegistryValueKind]::ExpandString)
             Write-Output "The operation completed successfully."
         }
    
         Exit $ERROR_SUCCESS
     }
    

    I explain the problem in more detail in a blog post.

    0 讨论(0)
  • 2020-11-22 11:22

    Building on @Michael Kropat's answer I added a parameter to prepend the new path to the existing PATHvariable and a check to avoid the addition of a non-existing path:

    function Add-EnvPath {
        param(
            [Parameter(Mandatory=$true)]
            [string] $Path,
    
            [ValidateSet('Machine', 'User', 'Session')]
            [string] $Container = 'Session',
    
            [Parameter(Mandatory=$False)]
            [Switch] $Prepend
        )
    
        if (Test-Path -path "$Path") {
            if ($Container -ne 'Session') {
                $containerMapping = @{
                    Machine = [EnvironmentVariableTarget]::Machine
                    User = [EnvironmentVariableTarget]::User
                }
                $containerType = $containerMapping[$Container]
    
                $persistedPaths = [Environment]::GetEnvironmentVariable('Path', $containerType) -split ';'
                if ($persistedPaths -notcontains $Path) {
                    if ($Prepend) {
                        $persistedPaths = ,$Path + $persistedPaths | where { $_ }
                        [Environment]::SetEnvironmentVariable('Path', $persistedPaths -join ';', $containerType)
                    }
                    else {
                        $persistedPaths = $persistedPaths + $Path | where { $_ }
                        [Environment]::SetEnvironmentVariable('Path', $persistedPaths -join ';', $containerType)
                    }
                }
            }
    
            $envPaths = $env:Path -split ';'
            if ($envPaths -notcontains $Path) {
                if ($Prepend) {
                    $envPaths = ,$Path + $envPaths | where { $_ }
                    $env:Path = $envPaths -join ';'
                }
                else {
                    $envPaths = $envPaths + $Path | where { $_ }
                    $env:Path = $envPaths -join ';'
                }
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题