首页 文章

设置Windows PowerShell路径变量

提问于
浏览
468

我发现设置PATH环境变量只影响旧的命令提示符 . PowerShell似乎有不同的环境设置 . 如何更改PowerShell(v1)的环境变量?

注意:

我希望永久更改我的更改,因此每次运行PowerShell时都不必设置它 . PowerShell有配置文件吗?像Unix上的Bash配置文件?

12 回答

  • 15

    就像JeanT's answer一样,我想要一个关于添加路径的抽象 . 与JeanT的答案不同,我需要它在没有用户交互的情况下运行 . 我正在寻找的其他行为:

    • 更新 $env:Path ,以便更改在当前会话中生效

    • 为将来的会话保留环境变量更改

    • 当相同路径已存在时,不添加重复路径

    如果它有用,这里是:

    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 ';'
        }
    }
    

    检查my gist以获取相应的 Remove-EnvPath 功能 .

  • 2

    您还可以使用以下命令永久修改用户/系统环境变量(即,将在shell重新启动时保持持久性):

    ### Modify a system environment variable ###
    [Environment]::SetEnvironmentVariable
         ("Path", $env:Path, [System.EnvironmentVariableTarget]::Machine)
    
    ### Modify a user environment variable ###
    [Environment]::SetEnvironmentVariable
         ("INCLUDE", $env:INCLUDE, [System.EnvironmentVariableTarget]::User)
    
    ### Usage from comments - add to the system environment variable ###
    [Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\bin", [EnvironmentVariableTarget]::Machine)
    
  • 5

    大多数答案都没有解决UAC . 这涵盖了UAC问题 .

    首先安装PowerShell社区扩展: choco install pscx 来自http://chocolatey.org/(您可能必须重新启动shell环境) .

    然后启用pscx

    Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser #allows scripts to run from the interwebs, such as pcsx
    

    然后使用 Invoke-Elevated

    Invoke-Elevated {Add-PathVariable $args[0] -Target Machine} -ArgumentList $MY_NEW_DIR
    
  • 322

    虽然当前接受的答案在路径变量从PowerShell的上下文中永久更新的意义上起作用,但它实际上并不更新存储在Windows注册表中的环境变量 .

    为此,您显然可以使用PowerShell:

    $oldPath=(Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).Path
    
    $newPath=$oldPath+’;C:\NewFolderToAddToTheList\’
    
    Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH –Value $newPath
    

    更多信息请访问博文Use PowerShell to Modify Your Environmental Path

    如果使用PowerShell社区扩展,则向环境变量路径添加路径的正确命令是:

    Add-PathVariable "C:\NewFolderToAddToTheList" -Target Machine
    
  • 564

    @Michael Kropat's回答的基础上,我添加了一个参数来预先添加现有 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 ';'
                }
            }
        }
    }
    
  • 192

    正如Jonathan Leaders提到here,重要的是运行命令/脚本提升以便能够更改 'machine' 的环境变量,但运行一些提升的命令并不想修改和扩展JeanT's answer以某种方式改变机器变量也可以即使脚本本身没有运行提升,也要执行:

    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
        }
    
    }
    
  • 44

    如果,在PowerShell会话期间,您需要暂时附加到PATH环境变量,您可以这样做:

    $env:Path += ";C:\Program Files\GnuWin32\bin"
    
  • 14

    我的建议就是这一点,我已经测试过这个将C:\ oracle \ x64 \ bin永久添加到Path,这很好用 .

    $ENV:PATH
    

    第一种方法就是:

    $ENV:PATH=”$ENV:PATH;c:\path\to\folder”
    

    但这种变化并非永久性,$ env:只要你关闭PowerShell终端并重新打开它,路径就会默认回到之前的状态 . 这是因为您已在会话级别而不是源级别(即注册表级别)应用了更改 . 要查看$ env:path的全局值,请执行以下操作:

    Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH
    

    或者,更具体地说:

    (Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH).path
    

    现在要更改它,首先我们捕获需要修改的原始路径:

    $oldpath = (Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH).path
    

    现在我们定义新路径应该是什么样子,在这种情况下,我们将附加一个新文件夹:

    $newpath = “$oldpath;c:\path\to\folder”
    

    注意:确保$ newpath看起来如何显示,如果没有,那么你可能会损坏你的操作系统 .

    现在应用新值:

    Set-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH -Value $newPath
    

    现在做最后一次检查它看起来如你所料:

    (Get-ItemProperty -Path ‘Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment’ -Name PATH).Path
    

    您现在可以重新启动您的powershell终端(甚至重启机器)并看到它不会再次回滚到它的旧值 . 请注意,路径的顺序可能会改变,因此它按字母顺序排列,因此请确保检查整行,以便更容易,您可以使用分号作为分隔符将输出拆分为行:

    ($env:path).split(“;”)
    
  • 9

    从PowerShell提示符:

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

    然后你应该看到文字:

    SUCCESS: Specified value was saved.
    

    重新启动会话,变量将可用 . setx 也可用于设置任意变量 . 在提示文档中键入 setx /? .

    在以这种方式弄乱路径之前,请确保通过在PowerShell提示符下执行 $env:path >> a.out 来保存现有路径的副本 .

  • 8

    可以使用 env: namespace / drive 信息更改实际环境变量 . 例如,此代码将更新路径环境变量:

    $env:Path = "SomeRandomPath";
    

    有一些方法可以永久保持环境设置,但如果您只是从PowerShell使用它们,那么使用您的配置文件启动设置可能要好得多 . 在启动时,PowerShell将运行它在My Documents文件夹下的WindowsPowerShell目录中找到的任何.ps1文件 . 通常,您已经有profile.ps1文件 . 我的电脑上的路径是

    c:\Users\JaredPar\Documents\WindowsPowerShell\profile.ps1
    
  • 4

    所有建议永久性更改的答案都有同样的问题:它们打破了路径注册表值 .

    SetEnvironmentVariableREG_EXPAND_SZ%SystemRoot%\system32 变为 REG_SZC:\Windows\system32

    路径中的任何其他变量也会丢失 . 使用 %myNewPath% 添加新的将不再起作用 .

    这是我用来解决这个问题的脚本 Set-PathVariable.ps1

    [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
     }
    

    我在a blog post中更详细地解释了这个问题 .

  • 1

    这将设置当前会话的路径,并提示用户永久添加它:

    function Set-Path {
        param([string]$x)
        $Env:Path+= ";" +  $x
        Write-Output $Env:Path
        $write = Read-Host 'Set PATH permanently ? (yes|no)'
        if ($write -eq "yes")
        {
            [Environment]::SetEnvironmentVariable("Path",$env:Path, [System.EnvironmentVariableTarget]::User)
            Write-Output 'PATH updated'
        }
    }
    

    您可以将此功能添加到默认配置文件( Microsoft.PowerShell_profile.ps1 ),通常位于 %USERPROFILE%\Documents\WindowsPowerShell .

相关问题