设置Windows PowerShell环境变量

953

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

注意:

我想使我的更改永久生效,这样我就不必每次运行PowerShell时都设置它。PowerShell是否有配置文件?就像Unix上的Bash配置文件一样?


1
我想要一个位于文件共享上的中央配置文件。同步很麻烦。通过使用. \computer\share\path\Profile.ps1创建存根配置文件似乎不是很好的解决办法(尝试Notepad $Profile)。如果有一种可以永久更改$Profile自动变量的方法就好了。 - Nathan Hartley
6
PATH环境变量确实会影响PowerShell命令提示符。不同的是,PowerShell不接受用引号括起来的路径。解决方法是:删除路径环境变量中所有的引号(")。 - Nilzor
4
如果您在使用PS > v1时遇到问题,请参考Nilzor上面的评论:使用以下命令可以删除PATH环境变量中所有路径中的引号,以便于您的会话:$($Env:PATH).Split(';') | %{ $str += "$($_.Trim('"'));" }; $Env:PATH=$str - d3r3kk
1
关于与 PowerShell 无关的持久更新,请参见:https://dev59.com/lcLra4cB1Zd3GeqPDCY1。请注意,应该避免使用基于 setx.exe[Environment]::SetEnvironmentVariable() 的解决方案,因为它们总是将 REG_EXPAND_SZ 定义替换为 REG_SZ 条目,这意味着动态引用其他环境变量的条目会被转换为静态条目。此外,setx.exe 具有 1024 个字符的硬长度限制。 - mklement0
如果遵循@mklement0的建议,可以使用PowerShell cmdlet Add-Path - dank8
1
这个回答解决了你的问题吗?使用PowerShell永久添加路径到Windows似乎不起作用 - dank8
24个回答

836

如果在 PowerShell 会话期间需要查看或 临时 修改 PATH 环境变量,则可以输入以下命令之一:

$env:Path                             # shows the actual content
$env:Path = 'C:\foo;' + $env:Path     # attach to the beginning
$env:Path += ';C:\foo'                # attach to the end


4
这个短语对于基于会话调用的操作非常有效,例如在mingw中...即 $env:PATH += ";c:\MinGW\msys\1.0\bin" ^ {some mingw bin ... } - Edward J Beckett
3
我该如何删除路径? - a06e
30
如果您需要在标准路径之前调用您的路径,请将其插入到开头 $env:Path = "C:\MyPath;$env:Path" - Michael Freidgeim
6
不要忘记在追加字符串的开头添加分号,就像@Kevin的评论中所示。这很明显,但是如果您只是复制/粘贴答案中的代码并且现有路径末尾没有分号,则可能会被忽略。我将尝试提交编辑。 - Matt Goodrich
2
要删除路径需要一些代码:$env:PATH = ($env:PATH -split ";" | %{ if($_ -ne "/path_to_remove") { $_ } }) -join ";" - karezza
显示剩余2条评论

781

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

$env:PATH = "SomeRandomPath";             (replaces existing path) 
$env:PATH += ";SomeRandomPath"            (appends to existing path)

使更改永久化

有方法可以使环境设置永久化,但如果您只是从 PowerShell 使用它们,最好使用 Powershell profiles 脚本。

每次启动新的 PowerShell 实例时,它都会查找特定的脚本文件(命名为profile文件),如果存在则执行它们。您可以编辑其中一个 profile 来自定义您的环境。

要知道计算机中这些profile脚本的位置,请键入:

$profile                                     
$profile.AllUsersAllHosts           
$profile.AllUsersCurrentHost        
$profile.CurrentUserAllHosts    
$profile.CurrentUserCurrentHost     

你可以编辑其中的一个,例如输入:

notepad $profile

51
$profile 是一个自动变量,它指向所有 PowerShell 主机的用户配置文件。 - JasonMArcher
16
请注意,(split-path $profile)(用于获取包含文件夹)可能包含多个配置文件:所有主机都应加载 profile.ps1,而 <host-name>_profile.ps1 只需由指定的主机加载。对于 PowerShell.exe (控制台主机),配置文件为 Microsoft.PowerShell_profile.ps1。 - Richard
15
如果我的“文档”文件夹中没有“WindowsPowerShell”文件夹,我该怎么办?我应该创建这个文件夹和文件吗?如果我想要将C:\path\to\file.ext添加到环境变量中,我应该在文件中放什么内容?编辑:我已经找到了。答案是要创建它。文件应该只包含一行:$env:path += ;C:\path\to\file.ext" - Lewistrick
10
默认情况下,您没有个人资料。我按照以下说明创建了一个资料:http://www.howtogeek.com/50236/customizing-your-powershell-profile/ - MikeB
19
小心操作,这会破坏你现有的路径。$env:Path = "SomeRandomPath";相反,看下面@mloskot的建议。 - John Mark
显示剩余7条评论

454

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

修改系统环境变量

[Environment]::SetEnvironmentVariable
     ("Path", $env:Path, [System.EnvironmentVariableTarget]::Machine)

修改用户环境变量

[Environment]::SetEnvironmentVariable
     ("INCLUDE", $env:INCLUDE, [System.EnvironmentVariableTarget]::User)

从评论中使用 - 将其添加到系统环境变量中

[Environment]::SetEnvironmentVariable(
    "Path",
    [Environment]::GetEnvironmentVariable("Path", [EnvironmentVariableTarget]::Machine) + ";C:\bin",
    [EnvironmentVariableTarget]::Machine)

如果您不想编写类型,也可以使用基于字符串的解决方案。

[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\bin", "Machine")

9
这对于访问受限系统非常有用。 - h0tw1r3
21
@AndresRiofrio,是的,这是永久性的。 用法:[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\bin", [EnvironmentVariableTartget::Machine) 在启动新的 PowerShell 会话之前,您将看不到此更改的结果。也就是说,如果您在运行此命令后立即检查 $env:Path,则会看到该命令之前的 $env:Path 。为了更新,请关闭并打开 shell 或启动新会话。 - FLGMwt
14
你可以替代整个.NET枚举,写入"Machine"或"User"字符串。来源:Technet - bouvierr
20
我认为答案还应该演示如何设置用户变量的用法,就像这样[Environment]::SetEnvironmentVariable("Path", [Environment]::GetEnvironmentVariable("Path", "User") + ";C:\bin", "User") - Saito
8
我希望你知道的是,这个答案会破坏你路径中任何动态(也称为扩展)的项目。例如,如果你的环境变量中有GIT_INSTALL_ROOT=c:\tools\gitPATH=...;%GIT_INSTALL_ROOT%\cmd;%GIT_INSTALL_ROOT%\mingw64\bin,那么你的路径中所有对GIT_INSTALL_ROOT变量的引用都将消失,因此它将被硬编码为某个固定的目录。 - maoizm
显示剩余15条评论

81

警告:在PowerShell提示符下执行$env:path >> a.out将您现有的路径保存副本,以防出现任何问题。

从PowerShell提示符下执行:

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

然后您应该会看到文本:

SUCCESS: Specified value was saved.

重新启动您的会话,这样变量就会可用了。 setx 也可以用来设置任意变量。在提示符处键入 setx /? 以获取文档。


6
似乎只有在“以管理员身份运行”时才起作用,之后仅对“以管理员身份运行”的 PowerShell 控制台生效,而不是普通的运行控制台。 - matanster
1
这里有一些关于Setx的微软官方文档 - user456814
19
哎呀,刚被setx的1024个字符限制给卡住了,好在我按照建议记录了$end:Path的现有值。这是一个需要注意的问题:http://superuser.com/questions/387619/overcoming-the-1024-character-limit-with-setx - Jonno
6
为什么不先设置$env:PATH,然后再使用setx /m PATH "$env:PATH",这样就可以在不重启 shell 的情况下本地和全局应用路径了? - tresf
4
不错!虽然setx不是本地的cmdlet,但仍然比那些冗长烦人的.NET Framework调用更好、更容易被忘记的选择!令人困惑的是,即使在PowerShell 7中,仍然没有官方的cmdlet来保持环境变量。这感觉像应该与“ls”具有相同功能的特性。 - Jonas
显示剩余4条评论

46
无痛、一行代码的示例解决方案
使用[Environment]::SetEnvironmentVariable(x,y,"Machine")和尝试以下三个命令来练习在PowerShell中设置和删除环境变量。
使用注意事项:
1. 在提升权限的PowerShell上运行这些命令(例如,以管理员权限运行)。 2. 每一步完成后,为了使命令生效,请关闭会话并重新打开。
添加/创建一个永久环境变量:
[Environment]::SetEnvironmentVariable("newEnvVar", "NewEnvVal", "Machine")

Machine 是一个适用于当前和未来用户的EnvironmentVariableTarget,与 User 目标相对。


修改环境变量:
[Environment]::SetEnvironmentVariable("oldEnvVar", "modifiedEnvVal", "Machine")

删除/移除变量:

[Environment]::SetEnvironmentVariable("oldEnvVar", "", "Machine")

5
确实,所有那些 Setx$Env 的答案让我头疼。这个回答很简洁优雅! - MD TAREQ HASSAN
我在我的Windows 10 21H2和Windows Terminal内的PowerShell 5.1中也遇到了这个问题--我们需要关闭会话并重新打开它以检查结果。或者两个命令--$ENV:ALICLOUD_ACCESSKEY_ID[Environment]::GetEnvironmentVariable('ALICLOUD_ACCESSKEY_ID')--都将返回空结果。这是某种错误吗? - Jing He
@JingHe其实我不确定我们能称其为漏洞!这只是他们设计的方式,我也不太舒服! - TechDogLover OR kiaNasirzadeh

45

JeanT的回答一样,我需要一个环绕路径添加的抽象。与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 ';'
    }
}

请查看我的代码片段,其中包含相应的Remove-EnvPath函数。


1
我在我的个人资料中添加了以下小功能:function Set-Env ([string]$Name, [string]$Value, [string]$Target = 'User') { Set-Item "Env:$Name" $Value [System.Environment]::SetEnvironmentVariable($Name, $Value, $Target) } 这使得使用PowerShell更加方便。 - Falco

22
所有关于永久更改的答案都有同样的问题:它们会破坏路径注册表值。 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
 }

我在一篇博客文章中更详细地解释了这个问题。


2
这句话应该改为:$newPath = $newPath -replace ";;",";" 吗? - Joe Johnston

22

虽然当前被接受的答案在 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

更多信息请参阅博客文章使用PowerShell修改您的环境路径

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

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

12

我的建议是这个:

我已经测试过,将C:\oracle\x64\bin永久地添加到环境变量Path中,这种方法可行。

$ENV:PATH

第一种方法就是简单地执行以下操作:
$ENV:PATH=”$ENV:PATH;c:\path\to\folder”

但这个更改并不是永久的。只要您关闭 PowerShell 终端并重新打开它,$env:path 就会恢复为之前的默认值。这是因为您将更改应用于会话级别,而不是源级别(即注册表级别)。要查看全局值 $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(“;”)

10

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接