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

注意:

我希望我的更改是永久性的,这样我就不必每次运行PowerShell时都设置它。PowerShell有配置文件吗?比如Unix上的Bash配置文件?


当前回答

如果在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

其他回答

需要明确的是,20世纪90年代的Windows方式,单击开始,右键单击这台PC,选择属性,然后选择高级系统设置,然后在弹出的对话框中,选择环境变量,在列表中双击PATH,然后使用新建,编辑,向上移动和向下移动,这些都仍然可以更改PATH。powershell,其余的Windows会得到你在这里设置的任何东西。

是的,你可以使用这些新方法,但旧方法仍然有效。在基本级别上,所有永久更改方法都是编辑注册表文件的受控方法。

这些脚本是幂等的(可以运行多次)。 它们更新Windows路径和当前/未来的Powershell会话:

永久添加路径

    $targetDir="c:\bin"
    $oldPath = [System.Environment]::GetEnvironmentVariable("Path","Machine")
    $oldPathArray=($oldPath) -split ';'
    if(-Not($oldPathArray -Contains "$targetDir")) {
        write-host "Adding $targetDir to Machine Path"
        $newPath = "$oldPath;$targetDir" -replace ';+', ';'
        [System.Environment]::SetEnvironmentVariable("Path",$newPath,"Machine")
        $env:Path = [System.Environment]::GetEnvironmentVariable("Path","User"),[System.Environment]::GetEnvironmentVariable("Path","Machine") -join ";"
    }
    write-host "Windows paths:"
    ($env:Path).Replace(';',"`n")

永久删除路径

    $targetDir="c:\bin"
    $oldPath = [System.Environment]::GetEnvironmentVariable("Path","Machine")
    $oldPathArray=($oldPath) -split ';'
    if($oldPathArray -Contains "$targetDir") {
        write-host "Removing $targetDir from Machine path"
        $newPathArray = $oldPathArray | Where-Object { $_ –ne "$targetDir" }
        $newPath = $newPathArray -join ";"
        [System.Environment]::SetEnvironmentVariable("Path",$newPath,"Machine")
        $env:Path = [System.Environment]::GetEnvironmentVariable("Path","User"),[System.Environment]::GetEnvironmentVariable("Path","Machine") -join ";"
    }
    write-host "Windows paths:"
    ($env:Path).Replace(';',"`n")

我的建议是:

我已经测试了将C:\oracle\x64\bin永久地添加到环境变量Path中,这工作正常。

$ENV:PATH

第一种方法很简单:

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

但这种改变不是永久的。$env:path将在关闭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(“;”)

打开PowerShell并运行:

[Environment]::SetEnvironmentVariable("PATH", "$ENV:PATH;<path to exe>", "USER")

我试着优化了SBF和Michael的代码,使其更紧凑。

我依赖于PowerShell的类型强制,它会自动将字符串转换为enum值,所以我没有定义查找字典。

我还取出了根据条件将新路径添加到列表中的块,这样工作只完成一次,并存储在变量中以供重用。

然后,根据$PathContainer参数,它会被永久地应用到Session中。

我们可以将代码块放在函数或ps1文件中,直接从命令提示符调用。我选择了DevEnvAddPath.ps1。

param(
    [Parameter(Position=0,Mandatory=$true)][String]$PathChange,

    [ValidateSet('Machine', 'User', 'Session')]
    [Parameter(Position=1,Mandatory=$false)][String]$PathContainer='Session',
    [Parameter(Position=2,Mandatory=$false)][Boolean]$PathPrepend=$false
)

[String]$ConstructedEnvPath = switch ($PathContainer) { "Session"{${env:Path};} default{[Environment]::GetEnvironmentVariable('Path', $containerType);} };
$PathPersisted = $ConstructedEnvPath -split ';';

if ($PathPersisted -notcontains $PathChange) {
    $PathPersisted = $(switch ($PathPrepend) { $true{,$PathChange + $PathPersisted;} default{$PathPersisted + $PathChange;} }) | Where-Object { $_ };

    $ConstructedEnvPath = $PathPersisted -join ";";
}

if ($PathContainer -ne 'Session') 
{
    # Save permanently to Machine, User
    [Environment]::SetEnvironmentVariable("Path", $ConstructedEnvPath, $PathContainer);
}

# Update the current session
${env:Path} = $ConstructedEnvPath;

我对DevEnvRemovePath.ps1做了类似的事情。

param(
    [Parameter(Position=0,Mandatory=$true)][String]$PathChange,

    [ValidateSet('Machine', 'User', 'Session')]
    [Parameter(Position=1,Mandatory=$false)][String]$PathContainer='Session'
)

[String]$ConstructedEnvPath = switch ($PathContainer) { "Session"{${env:Path};} default{[Environment]::GetEnvironmentVariable('Path', $containerType);} };
$PathPersisted = $ConstructedEnvPath -split ';';

if ($PathPersisted -contains $PathChange) {
    $PathPersisted = $PathPersisted | Where-Object { $_ -ne $PathChange };

    $ConstructedEnvPath = $PathPersisted -join ";";
}

if ($PathContainer -ne 'Session') 
{
    # Save permanently to Machine, User
    [Environment]::SetEnvironmentVariable("Path", $ConstructedEnvPath, $PathContainer);
}

# Update the current session
${env:Path} = $ConstructedEnvPath;

到目前为止,它们似乎是有效的。