Настройка переменной пути Windows PowerShell

Я обнаружил, что установка переменной среды PATH влияет только на старую командную строку. PowerShell, похоже,имеет разные параметры среды. Как изменить переменные среды для PowerShell (v1)?

Примечание:

Я хочу сделать свои изменения постоянными, поэтому мне не нужно устанавливать их каждый раз, когда я запускаю PowerShell. У PowerShell есть файл профиля? Что-то вроде профиля Bash в Unix?

12 ответов


изменение фактических переменных среды может быть сделано путем с помощью env: namespace / drive информация. Например, это код обновит переменную среды path:

$env:Path = "SomeRandomPath";

есть способы сделать настройки среды постоянными, но если вы используете их только из PowerShell, это, вероятно намного лучше использовать свой профиль для начала настройки. При запуске PowerShell будет запускать любой .ps1 файлы, которые он находит в каталоге WindowsPowerShell под мои документы папка. Как правило, у вас естьпрофиль.ps1 файл уже там. Путь на моем компьютере

c:\Users\JaredPar\Documents\WindowsPowerShell\profile.ps1

Если во время сеанса PowerShell вам необходимо временно измените переменную среды PATH, вы можете сделать это так:

$env:Path += ";C:\Program Files\GnuWin32\bin"

вы также можете постоянно изменять переменные среды пользователя/системы (т. е. будут постоянными при перезапуске оболочки) со следующим

### Modify system environment variable ###
[Environment]::SetEnvironmentVariable
     ( "Path", $env:Path, [System.EnvironmentVariableTarget]::Machine )

### Modify user environment variable ###
[Environment]::SetEnvironmentVariable
     ( "INCLUDE", $env:INCLUDE, [System.EnvironmentVariableTarget]::User )

### from comments ###
### Usage from comments - Add to the system environment variable ###
[Environment]::SetEnvironmentVariable("Path", $env:Path + ";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.


хотя текущий принятый ответ работает в том смысле, что переменная path постоянно обновляется из контекста 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

дополнительная информация здесь: http://blogs.technet.com/b/heyscriptingguy/archive/2011/07/23/use-powershell-to-modify-your-environmental-path.aspx

Если вы используете Расширения сообщества PowerShell, правильная команда для добавления пути к пути переменной среды:

Add-PathVariable "C:\NewFolderToAddToTheList" -Target Machine

как JeanT это!--5-->, Я хотел абстракцию вокруг добавления к пути. В отличие от ответа 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 ';'
    }
}

проверить мой Гист соответствующего


это задает путь для текущего сеанса и предлагает пользователю добавить его навсегда:

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.


все ответы, предполагающие постоянное изменение, имеют одну и ту же проблему: они нарушают значение реестра path.

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
 }

я объясняю проблему более подробно в блог пост.


As Лидеры Джонатан указано здесь, важно запустить команду / скрипт, повышенную, чтобы иметь возможность изменять переменные среды для 'машина', но запуск некоторых команд с повышенными правами не должен выполняться с расширениями сообщества, поэтому я хотел бы изменить и расширить 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
    }

}

большинство ответов не адресованы ОАК. Это касается вопросов ОАК.

Сначала установите расширения сообщества PowerShell:choco install pscx via 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

дом на @Майкл 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 к пути постоянно, и это работает нормально.

$ENV:PATH

первый способ просто сделать:

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

но это изменение не является постоянным, $env: path по умолчанию вернется к тому, что было раньше, как только вы закроете терминал powershell и снова откроете его. Это потому, что вы применили изменение на уровне сеанса, а не на уровне источника (который является уровнем реестра). Для просмотра глобальное значение $env: path, do:

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\Contro
l\Session Manager\Environment’ -Name PATH).Path

теперь вы можете перезапустить терминал powershell (или даже перезагрузить компьютер) и увидеть, что он не откатывается к старому значению снова. Обратите внимание, что порядок путей может измениться так, что он находится в алфавитном порядке, поэтому убедитесь, что вы проверяете всю строку, чтобы упростить ее, вы можете разделить вывод на строки, используя двоеточие в качестве делиметра:

($env:path).split(“;”)