Примечание. Этот ответ указывается от c до Windows, поскольку System.Environment.SetEnvironmentVariable
поддерживает только изменение постоянных определений переменных среды (через целевые области User
и Machine
) там. Однако основы того, как PowerShell определяет среду дочернего процесса, применимы и к Unix -подобным платформам.
[Environment]::SetEnvironmentVariable()
с целевой областью действия System.EnvironmentVariableTarget
аргумент User
или Machine
только обновляет постоянные определения переменных среды в реестре - он также не обновляет текущий процесс в памяти переменные .
Напротив, цель Process
обновляет только текущий процесс переменные непостоянно .
Таким образом, [Environment]::SetEnvironmentVariable('FOO','BAR','Process')
является эквивалентом $env:FOO = 'BAR'
Start-Process
по умолчанию использует текущие переменные среды процесса [1] и, следовательно, не видят переменные (пока), которые были созданы или обновлены путем нацеливания на области User
или Machine
в тот же процесс . [2]
Start-Process
Параметр -UseNewEnvironment
равен , в принципе предназначен для того, что вы хотите t: он предназначен для запуска нового процесса со значениями переменной среды , считанными из реестра , игнорируя значения вызывающего процесса - однако эта функция нарушена на PowerShell [Core ] v7.0 - см. этот выпуск GitHub .
Обходной путь предназначен для , а также определяет новую переменную в current процесс:
# Update both the registry and the current process.
foreach ($targetScope in 'User', 'Process') {
[Environment]::SetEnvironmentVariable('FOO', 'BAR', $targetScope)
}
# Start a new process with the new value in effect.
Start-Process -NoNewWindow -Wait powershell '-c \"`$env:FOO is: $env:FOO\"'
Обратите внимание, что - в отличие от того, что -UseNewEnvironment
должен сделать - это заставляет новый процесс наследовать все только для процесса (в памяти ) переменные / значения среды тоже.
[1] При запуске процессу присваивается блок переменных среды, часто копия родительского процесса блок (как это делает сам PowerShell по умолчанию при создании дочерних процессов). Этот блок запуска может отражать или не отражать текущие определения реестра. Внутрипроцессные модификации блока среды теряются при завершении процесса, если они явно не сохраняются, например, с [Environment]::SetEnvironmentVariable()
и целевыми областями User
или Machine
. Как и все программы, которые изменяют постоянно определенные переменные среды, [Environment]::SetEnvironmentVariable()
передает Windows сообщение WM_SETTINGCHANGE
как уведомление об изменении, но немногие программы предназначены для его прослушивания, и поэтому лишь немногие обновляют свои переменные среды в процессе. в ответ (что не подходит для всех программ).
[2] Однако, если вы начинаете новый процесс как администратор с -Verb RunAs
( Windows -только) с использованием учетных данных текущего пользователя , новый процесс будет видеть новые / обновленные определения, поскольку тогда не использует текущий процесс переменные среды и вместо этого считывает текущие определения из реестра.