1

Можно ли повторно использовать переменные среды в переменной среды Path из PowerShell?

Есть некоторые переменные окружения, такие как %SystemRoot% определенные и используемые в переменной Path ...;%SystemRoot%\system32;... просматривается в разделе «Дополнительные параметры системы».

В PowerShell они определены как $Env:SystemRoot и $Env:Path Часть этого пути разрешается с помощью ...;c:\windows\system32;...

Как создать и использовать такую переменную в Path? например, $Env:MyPath = 'c:\mypath' добавив его в Path как ...;%MyPath%\documents;... и получить одинаковый эффект как в дополнительных системных настройках, так и в PowerShell $Env:Path разрешение пути ?

1 ответ1

2

Боже мой, он полон переменных

Существует три типа переменных среды:

  1. Машина

    Переменная среды сохраняется или извлекается из ключа HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment в реестре операционной системы Windows. Когда пользователь создает переменную среды в заданной операции, операционная система сохраняет переменную среды в системном реестре, но не в текущем процессе. Если какой-либо пользователь на локальном компьютере запускает новый процесс, операционная система копирует переменную среды из реестра в этот процесс. Когда процесс завершается, операционная система уничтожает переменную среды в этом процессе. Однако переменная среды в реестре сохраняется до тех пор, пока пользователь не удалит ее программно или с помощью инструмента операционной системы.

  2. пользователь

    Переменная среды сохраняется или извлекается из ключа HKEY_CURRENT_USER\Environment в реестре операционной системы Windows. Когда пользователь создает переменную среды в заданной операции, операционная система сохраняет переменную среды в системном реестре, но не в текущем процессе. Если пользователь запускает новый процесс, операционная система копирует переменную среды из реестра в этот процесс. Когда процесс завершается, операционная система уничтожает переменную среды в этом процессе. Однако переменная среды в реестре сохраняется до тех пор, пока пользователь не удалит ее программно или с помощью инструмента операционной системы.

  3. Процесс

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

Вновь созданные с помощью $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. К сожалению, есть ряд причуда:

  1. Основная запись реестра для такой переменной должна иметь REG_EXPAND_SZ type
  2. Континентальный окр. переменная должна быть в алфавитном порядке меньше, чем контейнер env. переменная:

    Если определение переменной окружения var1 содержит другую переменную окружения var2, а имя var1 в алфавитном порядке меньше, чем имя var2 (т.е. strcmp (var1, var2) <0), тогда var2 не будет расширен. Похоже, это происходит потому, что когда Windows сначала устанавливает переменные среды, они создаются в алфавитном порядке, поэтому var2 не существует до тех пор, пока var1 не будет создан (и, следовательно, расширение не может быть выполнено).

  3. Для 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
);

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .