我发现设置PATH环境变量只影响旧的命令提示符。PowerShell似乎有不同的环境设置。如何更改PowerShell (v1)的环境变量?
注意:
我希望我的更改是永久性的,这样我就不必每次运行PowerShell时都设置它。PowerShell有配置文件吗?比如Unix上的Bash配置文件?
我发现设置PATH环境变量只影响旧的命令提示符。PowerShell似乎有不同的环境设置。如何更改PowerShell (v1)的环境变量?
注意:
我希望我的更改是永久性的,这样我就不必每次运行PowerShell时都设置它。PowerShell有配置文件吗?比如Unix上的Bash配置文件?
当前回答
在@ali Darabi的回答中编辑注册表键对我来说是最好的,但是 当我没有Powershell的权限时。所以我直接在regedit里编辑。
我想在这个回答中进一步展开这个主题。
重新启动Powershell也不足以传播更改。我必须打开任务管理器并重新启动explorer.exe以触发注册表的重新加载。
导航注册表可能相当乏味,所以为了保持用户友好的体验,你可以从Powershell执行这个:
REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit" /v "LastKey" /d "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment" /f; regedit
它将最后打开的窗口设置为某个注册表路径,这样当您下次打开regedit时,它将以适当的键打开。
其他回答
就像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函数。
在@ali Darabi的回答中编辑注册表键对我来说是最好的,但是 当我没有Powershell的权限时。所以我直接在regedit里编辑。
我想在这个回答中进一步展开这个主题。
重新启动Powershell也不足以传播更改。我必须打开任务管理器并重新启动explorer.exe以触发注册表的重新加载。
导航注册表可能相当乏味,所以为了保持用户友好的体验,你可以从Powershell执行这个:
REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit" /v "LastKey" /d "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment" /f; regedit
它将最后打开的窗口设置为某个注册表路径,这样当您下次打开regedit时,它将以适当的键打开。
我的建议是:
我已经测试了将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中设置和删除环境变量。
使用注意事项:
在提升的PowerShell上运行这些命令(例如,具有管理员权限)。 在每一步之后,为了使您的命令工作,关闭会话并再次打开它。
添加/创建永久环境变量:
[Environment]::SetEnvironmentVariable("MyEnvVar", "NewEnvValue", "Machine")
Machine是一个环境变量目标,将应用于当前和未来的用户,而不是User目标。
修改/改变环境变量:
[Environment]::SetEnvironmentVariable("MyEnvVar", "NewerEnvValue", "Machine")
删除/删除变量:
[Environment]::SetEnvironmentVariable("MyEnvVar", "", "Machine")
我试着优化了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;
到目前为止,它们似乎是有效的。