Я выяснил, что настройка переменной среды PATH влияет только на старую командную строку. Кажется, что у PowerShell разные настройки среды. Как изменить переменные среды для PowerShell (v1)?
Примечание:
Я хочу, чтобы мои изменения были постоянными, поэтому мне не нужно устанавливать его каждый раз, когда я запускаю PowerShell. У PowerShell есть файл профиля? Что-то вроде профиля Bash на Unix?
Изменение фактических переменных окружения может быть выполнено с помощью
используя информацию env: namespace / drive
. Например, это
код обновит переменную среды пути:
$env:Path = "SomeRandomPath";
Есть способы сделать настройки среды постоянными, но если вы используете их только из PowerShell, возможно, намного лучше использовать свой профиль, чтобы инициировать Настройки. При запуске PowerShell запускает любой .ps1 файлы, которые он находит в каталоге WindowsPowerShell в разделе Мои документы. Как правило, у вас есть profile.ps1 файл уже есть. Путь на моем компьютере
c:\Users\JaredPar\Documents\WindowsPowerShell\profile.ps1
Если какое-то время во время сеанса PowerShell вам необходимо временно добавить переменную среды PATH, вы можете сделать это следующим образом:
$env:Path += ";C:\Program Files\GnuWin32\bin"
Вы также можете постоянно изменять пользовательские/системные переменные среды (т.е. они будут постоянными при перезапуске оболочки) следующим образом:
### 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 /?
в приглашении для документации.
Прежде чем возиться с вашим путем таким образом, убедитесь, что вы сохранили копию существующего пути, выполнив $env:path >> a.out
в приглашении PowerShell.
Как и ответ 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
.
Хотя текущий принятый ответ работает в том смысле, что переменная пути постоянно обновляется из контекста 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
Все ответы, предлагающие постоянное изменение, имеют одну и ту же проблему: они нарушают значение реестра пути.
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
}
Я объясню проблему более подробно в блоге.
Это устанавливает путь для текущего сеанса и предлагает пользователю добавить его навсегда:
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
.
Как Лидеры Джонатана упомянули здесь, важно запустить команду / script повышенную до иметь возможность изменять переменные среды для "машины" , но выполнение некоторых команд с повышенными значениями не обязательно должно выполняться с помощью расширений Community, поэтому я хотел бы изменить и расширить , ответить, что изменение машинных переменных также может выполняться, даже если сам script не запускается:
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
}
}
Большинство ответов не адресованы UAC. Это касается вопросов UAC.
Сначала установите расширения сообщества PowerShell: choco install pscx
через http://chocolatey.org/ (возможно, вам придется перезапустить среду оболочки).
Затем включите 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, я добавил параметр для добавления нового пути к существующей PATH
и проверку, чтобы избежать добавления несуществующего пути:
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: 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(";")
Успешно проверено с помощью кода С#.
//**file location - User Variables**
string fileLocation = Environment.GetEnvironmentVariable("AZURE_FILE_PATH", EnvironmentVariableTarget.User);
//**file location - System Variables**
string fileLocation = Environment.GetEnvironmentVariable("AZURE_FILE_PATH", EnvironmentVariableTarget.Machine);
"
) в переменной окружения пути