Боже мой, он полон переменных
Существует три типа переменных среды:
Машина
Переменная среды сохраняется или извлекается из ключа HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment в реестре операционной системы Windows. Когда пользователь создает переменную среды в заданной операции, операционная система сохраняет переменную среды в системном реестре, но не в текущем процессе. Если какой-либо пользователь на локальном компьютере запускает новый процесс, операционная система копирует переменную среды из реестра в этот процесс. Когда процесс завершается, операционная система уничтожает переменную среды в этом процессе. Однако переменная среды в реестре сохраняется до тех пор, пока пользователь не удалит ее программно или с помощью инструмента операционной системы.
пользователь
Переменная среды сохраняется или извлекается из ключа HKEY_CURRENT_USER\Environment в реестре операционной системы Windows. Когда пользователь создает переменную среды в заданной операции, операционная система сохраняет переменную среды в системном реестре, но не в текущем процессе. Если пользователь запускает новый процесс, операционная система копирует переменную среды из реестра в этот процесс. Когда процесс завершается, операционная система уничтожает переменную среды в этом процессе.
Однако переменная среды в реестре сохраняется до тех пор, пока пользователь не удалит ее программно или с помощью инструмента операционной системы.
Процесс
Переменная среды сохраняется или извлекается из блока среды, связанного с текущим процессом. Пользователь создает переменную среды в заданной операции. Когда процесс завершается, операционная система уничтожает переменную среды в этом процессе.
Вновь созданные с помощью $env:
переменные среды в PowerShell имеют тип Process
. Для отображения переменной в Advanced System Settings
это должна быть переменная уровня Machine
или User
. Для создания переменной определенного уровня используйте Environment.Метод SetEnvironmentVariable :
[Environment]::SetEnvironmentVariable('MyPath', 'c:\mypath', 'User')
[Environment]::SetEnvironmentVariable('MyPath', 'c:\mypath', 'Machine')
Обратите внимание, что установка переменных среды уровня Machine
требует повышения прав.
Ты читаешь меня, HAL?
Итак, вы хотите встроить одну переменную среды в другую и развернуть ее? В конце концов, Microsoft делает это полностью, например, переменные TEMP
и TMP
для каждого пользователя содержат USERPROFILE
env.var. К сожалению, есть ряд причуда:
- Основная запись реестра для такой переменной должна иметь
REG_EXPAND_SZ type
Континентальный окр. переменная должна быть в алфавитном порядке меньше, чем контейнер env. переменная:
Если определение переменной окружения var1 содержит другую переменную окружения var2, а имя var1 в алфавитном порядке меньше, чем имя var2 (т.е. strcmp (var1, var2) <0), тогда var2 не будет расширен. Похоже, это происходит потому, что когда Windows сначала устанавливает переменные среды, они создаются в алфавитном порядке, поэтому var2 не существует до тех пор, пока var1 не будет создан (и, следовательно, расширение не может быть выполнено).
Для PATH
между записями не должно быть пробелов:
Неверно: c:\path1; c:\Maven\bin\; c:\path2\
Исправьте: c:\path1;c:\Maven\bin\;c:\path2\
Кроме того, если вы попытаетесь использовать Среду.SetEnvironmentVariable метод, как это:
$Path = [Environment]::GetEnvironmentVariable('Path', 'Machine')
[Environment]::SetEnvironmentVariable('MyPath', 'c:\mypath', 'Machine')
[Environment]::SetEnvironmentVariable('Path', "%MyPath%;$Path", 'Machine')
Это не приведет к желаемому результату, потому что только что созданная PATH
будет иметь тип REG_EXPAND_SZ
, но REG_SZ
.
Откройте двери в отсек, HAL
Учитывая, что SetEnvironmentVariable
не имеет средств для управления результирующим типом записи реестра, вы должны использовать альтернативу: напрямую изменить реестр, чтобы создать запись типа REG_EXPAND_SZ
.
$Path = [Environment]::GetEnvironmentVariable('Path','Machine')
[Environment]::SetEnvironmentVariable('MyPath', 'c:\mypath', 'Machine')
[Microsoft.Win32.Registry]::SetValue(
'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment',
'Path',
"%MyPath%;$Path",
[Microsoft.Win32.RegistryValueKind]::ExpandString
)
Недостатки этого метода в том, что он не передает сообщение WM_SETTINGCHANGE
всем окнам в системе, поэтому любые заинтересованные приложения (такие как Windows Explorer, Диспетчер программ, Диспетчер задач, Панель управления и т.д.) Могут выполнять обновление. ,
Чтобы смягчить это, вы можете транслировать сообщение самостоятельно:
if (-not ('Win32.NativeMethods' -as [type])) {
# import SendMessageTimeout from Win32
Add-Type -Namespace Win32 -Name NativeMethods -MemberDefinition @'
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd,
uint Msg,
UIntPtr wParam,
string lParam,
uint fuFlags,
uint uTimeout,
out UIntPtr lpdwResult);
'@
}
$HWND_BROADCAST = [System.IntPtr]0xffff
$WM_SETTINGCHANGE = 0x1a
$result = [System.UIntPtr]::Zero
# Notify all windows of environment block change
[Win32.NativeMethods]::SendMessageTimeout(
$HWND_BROADCAST, $WM_SETTINGCHANGE,
[System.UIntPtr]::Zero,
'Environment',
2,
5000,
[ref]$result
);