Обновления $env:EnvVarName
влияют только на текущий процесс - постоянные изменения через реестр не вносятся:
$env:EnvVarName = 'foo'
эквивалентно вызову. NET метод System.Environment.SetEnvironmentVariable
следующим образом:
[Environment]::SetEnvironmentVariable('EnvVarName', 'foo', 'Process')
То есть область действия обновления - текущий процесс .
Только если вы замените 'User'
или 'Machine'
на 'Process'
в вышеуказанном вызове (поддерживается только Windows [1] ), вы постоянно обновите среду переменные в реестре (для текущего пользователя или локального компьютера ( всех пользователей) соответственно), для будущих сеансов (процессов) [2 ] .
Начиная с PowerShell [Core] 7.0, PowerShell-родной не существует способа постоянного обновления переменных среды, но его введение - обсуждается на GitHub .
Другими словами: , если вы хотите обновить не только определение на основе реестра, но и значение в текущем процессе вам нужно сделать оба звонка ; Например, для текущего пользователя:
# Windows only: Update / create a persistent definition for the current user,
# stored in the registry.
[Environment]::SetEnvironmentVariable('EnvVarName', 'foo', 'User')
# Update value for current process too.
$env:EnvVarName = 'foo'
Или, больше в духе DRY:
'User', 'Process' | foreach {
[Environment]::SetEnvironmentVariable('EnvVarName', 'foo', $_)
}
Если новое значение должно быть основано для существующего из заданной области реестра получить значение c для области видимости через System.Environment.GetEnvironmentVariable
; Например:
# Get the registry-based *user* value
[Environment]::GetEnvironmentVariable('Path', 'User')
Важные замечания для переменной среды Path
($env:PATH
) в Windows:
Среда Path
Эта особенность заключается в том, что это составное значение: при запуске процесса внутрипроцессное значение равно сцеплению значения Machine
(локальный компьютер, для всех пользователей) и значение User
(текущий пользователь).
Поэтому, если вы хотите изменить (добавить) существующий Path
, лучше , а не , чтобы Определите новое значение, просто добавив к существующему значению в процессе ($env:Path
), потому что вы будете дублировать Machine
или User
значений, в зависимости от того, на какую область вы нацеливаетесь.
Вместо этого выборочно извлекайте существующее значение из целевой области, изменяйте это значение (обычно добавляя каталог, а затем записывайте измененное значение обратно в ту же область.
Чтобы надежно сделать ту же модификацию эффективной в текущем процессе, тоже нетривиально, учитывая, что внутрипроцессная копия $env:Path
могла быть изменена, однако в простом В случае добавления нового каталога к пути пользователя, вы можете просто сделать $env:Path += ';' + $newDir
, вы можете избежать этого простого подхода и в других случаях, но учтите, что поведение может отличаться, учитывая, что порядок в которых каталоги перечислены в $env:Path
значения.
Пример:
# New dir. to add to the *user's* path
$newDir = 'c:\foo\bin'
# Get current value *from the registry*
$userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
# Append the new dir and save back to the registry.
[Environment]::SetEnvironmentVariable('Path', ($userPath + ';' + $newDir), 'User')
# To also update the current process, append $newDir to the in-process
# variable, $env:Path
$env:Path += ';' + $newDir
В качестве отступления: Вкл Unix -подобные платформы , разделитель - :
, а не ;
(отражен в [System.IO.Path]::PathSeparator
, а с учетом регистра имя переменной равно Path
. Как указано,. NET принципиально не предлагает упорство nt определения переменных среды на Unix -подобных платформах (по состоянию на NET Core 3.1), потому что на разных платформах нет унифицированного собственного механизма для этого.
[1] На Unix -подобных платформах с таргетингом на User
или Machine
тихо игнорируется с. NET Core 3.1
[ 2] Предупреждение : новые процессы, созданные непосредственно текущим сеансом PowerShell (прямой вызов, Start-Process
, Start-Job
), делают не , но все же видят изменения в реестре, поскольку они наследуют текущая среда сеанса.