Настройка переменных среды Windows PowerShell

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

Примечание:

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

Ответ 1

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

$env:Path = "SomeRandomPath";             (replaces existing path) 
$env:Path += ";SomeRandomPath"            (appends to existing path)

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

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

Ответ 2

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

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

Ответ 3

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

Изменить системную переменную среды

[Environment]::SetEnvironmentVariable
     ("Path", $env:Path, [System.EnvironmentVariableTarget]::Machine)

Изменить переменную среды пользователя

[Environment]::SetEnvironmentVariable
     ("INCLUDE", $env:INCLUDE, [System.EnvironmentVariableTarget]::User)

Использование из комментариев - добавьте в системную переменную среды

[Environment]::SetEnvironmentVariable(
    "Path",
    [Environment]::GetEnvironmentVariable("Path", [EnvironmentVariableTarget]::Machine) + ";C:\bin",
    [EnvironmentVariableTarget]::Machine)

Строковое решение также возможно, если вы не хотите писать типы

[Environment]::SetEnvironmentVariable("Path", $env:Path + ";C:\bin", "Machine")

Ответ 4

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

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

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

SUCCESS: Specified value was saved.

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

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

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.

Ответ 9

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

Ответ 10

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

Ответ 11

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

}

Ответ 12

Вот мое предложение:

Я проверил это, чтобы добавить 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(';')

Ответ 13

Откройте PowerShell и запустите:

[Environment]::SetEnvironmentVariable("PATH", "$ENV:PATH;<path to exe>", "USER")

Ответ 14

Я попытался немного оптимизировать код SBF и Майкла, чтобы сделать его более компактным.

Я полагаюсь на приведение типов PowerShell, когда он автоматически преобразует строки в значения перечисления, поэтому я не определил словарь поиска.

Я также вытащил блок, который добавляет новый путь в список на основе условия, чтобы работа выполнялась один раз и сохранялась в переменной для повторного использования.

Затем он применяется постоянно или только к $PathContainer в зависимости от параметра $PathContainer.

Мы можем поместить блок кода в функцию или файл 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;

Пока что, похоже, они работают.

Ответ 15

В PowerShell можно перейти к каталогу переменных среды, набрав:

Set-Location Env:

Это приведет вас в каталог Env:>. Из этого каталога:

Чтобы увидеть все переменные среды, введите:

Env:\> Get-ChildItem

Чтобы увидеть конкретную переменную среды, введите:

Env:\> $Env:<variable name>, e.g. $Env:Path

Чтобы установить переменную среды, введите:

Env:\> $Env:<variable name> = "<new-value>", e.g. $Env:Path="C:\Users\"

Чтобы удалить переменную среды, введите:

Env:\> remove-item Env:<variable name>, e.g. remove-item Env:SECRET_KEY

Дополнительная информация содержится в Об переменных среды.

Ответ 16

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

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