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

476

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

Примечание:

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

  • 1
    Мне бы хотелось, чтобы центральный профиль находился в общей папке. Синхронизация - это боль. Создание профиля заглушки с. \\ computer \ share \ path \ Profile.ps1 выглядит как кладж (попробуйте Notepad $ Profile). Было бы хорошо, если бы существовал способ навсегда изменить автоматическую переменную $ Profile.
  • 5
    Никакая среда PATH также не влияет на командную строку powershell. Однако отличается то, что powershell не принимает пути, заключенные в кавычки. Решение: удалите все заключающие в кавычки ( " ) в переменной окружения пути
Показать ещё 1 комментарий
Теги:
powershell

13 ответов

309
Лучший ответ

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

$env:Path = "SomeRandomPath";

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

c:\Users\JaredPar\Documents\WindowsPowerShell\profile.ps1
  • 31
    $ profile - это автоматическая переменная, которая указывает на ваш профиль пользователя для всех хостов PowerShell.
  • 15
    Обратите внимание, что (split-path $ profile) (чтобы получить содержащую папку) может содержать несколько файлов профиля: profile.ps1 должен быть загружен всеми хостами, <host-name> _profile.ps1 только указанным хостом. Для PowerShell.exe (хост консоли) это Microsoft.PowerShell_profile.ps1.
Показать ещё 5 комментариев
598

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

$env:Path += ";C:\Program Files\GnuWin32\bin"
  • 4
    +1 :: Этот однострочный довольно эффективен для вызовов на основе сеанса, как в случае с mingw ... IE $ env: PATH + = "; c: \ MinGW \ msys \ 1.0 \ bin" ^ {некоторый mingw bin ... }
  • 2
    и как мне удалить путь?
Показать ещё 6 комментариев
205

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

### 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)
  • 12
    Это навсегда, верно?
  • 3
    Это очень полезно для систем с ограниченным доступом.
Показать ещё 10 комментариев
47

В командной строке PowerShell:

setx PATH "$env:path;\the\directory\to\add" -m

Затем вы должны увидеть текст:

SUCCESS: Specified value was saved.

Перезагрузите сеанс, и переменная будет доступна. setx также может использоваться для установки произвольных переменных. Введите setx /? в приглашении для документации.

Прежде чем возиться с вашим путем таким образом, убедитесь, что вы сохранили копию существующего пути, выполнив $env:path >> a.out в приглашении PowerShell.

  • 3
    Кажется, работает только при «работе от имени администратора», и после этого вступает в силу только для «работающих от имени администратора» консолей PowerShell, а не регулярно работающих.
  • 1
    Вот некоторая официальная документация Microsoft для Setx .
Показать ещё 2 комментария
15

Как и ответ 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.

14

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

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

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
 }

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

8

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

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.

5

Как Лидеры Джонатана упомянули здесь, важно запустить команду / 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
    }

}
4

Большинство ответов не адресованы 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
2

Опираясь на ответ @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 ';'
            }
        }
    }
}
1

МОЕ ПРЕДЛОЖЕНИЕ ЭТО ОДИН, Я ПРОВЕРИЛ ЭТО, ЧТОБЫ ДОБАВИТЬ 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(";")
-2

Успешно проверено с помощью кода С#.

//**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);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню