Повторне використання змінних середовища в Path


1

Чи можливо повторно використовувати змінні середовища в змінній середовища Path від PowerShell?

Є деякі змінні середовища, такі як %SystemRoot%визначені, і використовуються в змінній Шлях, ...;%SystemRoot%\system32;...переглянуті в розширених налаштуваннях системи.

У PowerShell вони визначені як $Env:SystemRootі $Env:Pathчастина цього шляху вирішена за допомогою...;c:\windows\system32;...

Як створити та використовувати таку власну змінну в Шляху? наприклад, $Env:MyPath = 'c:\mypath'додавши його до Path like ...;%MyPath%\documents;...і отримати однаковий ефект як у розширених налаштуваннях системи, так і в $Env:Pathроздільній здатності PowerShell ?

Відповіді:


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змінна середовища рівня рівня потребує підвищення.

Ти мене читаєш, ХАЛ?

Отже, ви хочете вставити одну змінну середовища всередину іншої та її розширити? Зрештою, Microsoft робить все так, наприклад, на користувача TEMPта TMPзмінні містять USERPROFILEenv.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\

Крім того, якщо ви спробуєте використати метод 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
);

дякую за широкий коментар, чи можна повторно використовувати одну змінну всередині якоїсь частини одного із шляхів у $ Env: Шлях?
Чесноков Юрій

Так, але потрібна деяка збірка. Див. Оновлення.
битфоркер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.