我发现设置PATH环境变量只影响旧的命令提示符。PowerShell似乎有不同的环境设置。如何更改PowerShell (v1)的环境变量?
注意:
我希望我的更改是永久性的,这样我就不必每次运行PowerShell时都设置它。PowerShell有配置文件吗?比如Unix上的Bash配置文件?
我发现设置PATH环境变量只影响旧的命令提示符。PowerShell似乎有不同的环境设置。如何更改PowerShell (v1)的环境变量?
注意:
我希望我的更改是永久性的,这样我就不必每次运行PowerShell时都设置它。PowerShell有配置文件吗?比如Unix上的Bash配置文件?
当前回答
这些脚本是幂等的(可以运行多次)。 它们更新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")
其他回答
更改实际的环境变量可以通过 使用env:命名空间/驱动器信息。例如,这个 代码将更新path环境变量:
$env:Path = "SomeRandomPath"; (replaces existing path)
$env:Path += ";SomeRandomPath" (appends to existing path)
让改变永久化
有办法让环境设置永久存在,但是 如果你只从PowerShell中使用它们,它可能 使用Powershell配置文件脚本更好。
每次Powershell的一个新实例启动时,它都会查找特定的脚本文件(称为配置文件),如果它们存在,就执行它们。您可以编辑这些概要文件中的一个来定制您的环境。
要了解这些配置文件脚本在您的计算机中的位置,请键入:
$profile
$profile.AllUsersAllHosts
$profile.AllUsersCurrentHost
$profile.CurrentUserAllHosts
$profile.CurrentUserCurrentHost
你可以编辑其中一个,例如,输入:
notepad $profile
所有建议永久更改的答案都有相同的问题:它们破坏了路径注册表值。
SetEnvironmentVariable将REG_EXPAND_SZ值%SystemRoot%\system32转换为c:\ windows \system32的REG_SZ值。
路径中的任何其他变量也会丢失。使用%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
}
我在一篇博文中更详细地解释了这个问题。
这些脚本是幂等的(可以运行多次)。 它们更新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")
如果在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
正如Jonathan Leaders在这里提到的,运行提升的命令/脚本来改变“machine”的环境变量是很重要的,但是运行一些提升的命令并不一定要用社区扩展来完成,所以我想在某种程度上修改和扩展JeanT的回答,即使脚本本身没有运行提升,也可以改变机器变量:
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
}
}