Боже мій, це повно змінних
Існує три типи змінних середовища :
Машина
Змінна середовища зберігається або отримується з
ключа 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
змінна середовища рівня рівня потребує підвищення.
Ти мене читаєш, ХАЛ?
Отже, ви хочете вставити одну змінну середовища всередину іншої та її розширити? Зрештою, 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\
Крім того, якщо ви спробуєте використати метод Environment.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, Менеджер програм, Диспетчер завдань, Панель управління тощо) можуть здійснити оновлення.
Щоб пом'якшити це, ви можете транслювати повідомлення самостійно:
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
);