我发现设置PATH环境变量只会影响旧的命令提示符。 PowerShell似乎有不同的环境设置。如何更改PowerShell(v1)的环境变量?
注意:
我希望永久更改我的更改,因此每次运行PowerShell时都不必设置它。 PowerShell有配置文件吗?像Unix上的Bash配置文件?
可以使用env: namespace / drive
信息更改实际环境变量。例如,此代码将更新路径环境变量:
$env:Path = "SomeRandomPath"; (replaces existing path)
$env:Path += ";SomeRandomPath" (appends to existing path)
有一些方法可以永久保持环境设置,但如果您只是从PowerShell使用它们,那么使用您的配置文件启动设置可能要好得多。在启动时,PowerShell将运行它在My Documents文件夹下的WindowsPowerShell
目录中找到的任何.ps1文件。通常,您已经有profile.ps1文件。我的电脑上的路径是
C:\Users\JaredPar\Documents\WindowsPowerShell\profile.ps1
大多数答案都不是针对UAC。这涵盖了UAC问题。
首先通过choco install pscx
安装PowerShell社区扩展: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
在@Michael Kropat's回答的基础上,我添加了一个参数来预先添加现有PATH
variable的新路径,并检查以避免添加不存在的路径:
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 ';'
}
}
}
}
我的建议就是这个,我已经测试了这个将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(“;”)
我依赖于PowerShell的类型强制,它自动将字符串转换为枚举值,所以我没有定义查找字典。
我还根据条件拉出了将新路径添加到列表中的块,以便工作完成一次并存储在变量中以便重复使用。
然后根据$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;
到目前为止,他们似乎工作。
打开PowerShell并运行:
[Environment]::SetEnvironmentVariable("PATH", "$ENV:PATH;<path to exe>", "USER")
如果,在PowerShell会话期间的某个时间,您需要临时追加到PATH环境变量,您可以这样做:
$env:Path += ";C:\Program Files\GnuWin32\bin"
您还可以使用以下命令永久修改用户/系统环境变量(即,将在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",
[Environment]::GetEnvironmentVariable("Path", [EnvironmentVariableTarget]::Machine) + ";C:\bin",
[EnvironmentVariableTarget]::Machine)
从PowerShell提示符:
setx PATH "$env:path;\the\directory\to\add" -m
然后你应该看到文字:
SUCCESS: Specified value was saved.
重新启动会话,变量将可用。 setx
也可用于设置任意变量。在提示文档时键入setx /?
。
在以这种方式弄乱路径之前,请确保通过在PowerShell提示符下执行$env:path >> a.out
来保存现有路径的副本。
像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
函数。
虽然当前接受的答案在路径变量从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
所有建议永久性更改的答案都有同样的问题:它们打破了路径注册表值。
SetEnvironmentVariable
将REG_EXPAND_SZ
值%SystemRoot%\system32
变成了REG_SZ
的C:\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中更详细地解释了这个问题。
这将设置当前会话的路径并提示用户永久添加它:
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
。
正如Jonathan Leaders提到here,重要的是运行命令/脚本提升以便能够更改“机器”的环境变量,但运行一些命令提升不必使用社区扩展,所以我想以某种方式修改和扩展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
}
}