2017-02-21 40 views
0

У меня есть приложение C#, которое при запуске задает некоторые переменные среды. Эти переменные среды должны быть установлены в системном масштабе.Расширение переменной среды Windows: Admin vs Non-Admin

Я использую этот код, чтобы на самом деле сделать набор.

public static void SetEnvironmentVariable(string _keyName, string _value, RegistryValueKind _type) 
    { 
     using (RegistryKey reg = Registry.LocalMachine.OpenSubKey(@"SYSTEM\CurrentControlSet\Control\Session Manager\Environment", true)) 
     { 
      if (reg != null) 
      { 
       reg.SetValue(_keyName, _value, _type); 
      } 
      else 
      { 
       string x = 
        string.Format(
         "Could find registry key that hosts Environment Variables: SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"); 
       App.AppLogger.Error(x); 
       throw new Exception(x); 
      } 
     } 
    } 

Этот код работает, но я замечаю странное поведение. Сразу после запуска моего приложения и этого кода я запускаю cmd как обычный пользователь и просматриваю среду, используя команду «set». Он не показывает никаких изменений.

Затем я запускаю подсказку cmd как admin и запускаю set. Он показывает изменения. Мало того, он показывает полностью расширенные переменные. Где ALLFOO = Foo и PATH = C: \ Windows \ System32;% ALLFOO% ;, команда set показывает PATH = C: \ Windows \ System32; Foo ;.

Затем я выхожу и снова включаюсь. Затем я запускаю cmd как обычный пользователь. I type set, и он показывает новые переменные среды, но не расширен. Показывает PATH = C: \ Windows \ System32;% ALLFOO%; (По какой-то причине, по-видимому, нет проблем с расширением% SYSTEMROOT%.)

Я получаю, что выход из системы и обратно приводит к запуску нового Explorer.exe, чтобы получить новые env vars для CMD обычного пользователя. exe, но я не понимаю, почему они не расширены.

Зачем запускать cmd и устанавливать как администратор показывать полностью расширенные переменные среды и запускать cmd и устанавливать как обычный пользователь, не так ли?

При настройке env vars в программе C# я использую перечисление RegistryValueKind.ExpandString.

Редактировать: Мне известно о порядке времени объявления для времени расширения с системными переменными и отредактировал пример вопроса, чтобы отразить это.

ответ

0

Изменения в переменных среды не являются видимыми. Необходимо выполнить notify текущие процессы изменений в реестре.

И вы должны помнить, что среда, которую вы видите в процессе (ваши окна cmd) не читается из реестра, наследуется от ее родительского процесса. Вы можете отправить уведомление, но некоторые процессы будут обрабатывать его, а некоторые - нет.

Остальные проблемы следует объяснить порядок загрузки среды:

  • Некоторые значения извлекаются из реестра перед обработкой самой среды. %systemroot% определяются в

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SystemRoot 
    
  • среды Системы загружается

    • REG_SZ переменных, в алфавитном порядке, являются первым
    • прочитанных
    • REG_EXPAND_SZ, в алфавитном порядке, является прочитанным. Когда значения REG_SZ были прочитаны, их можно развернуть.Если переменная REG_EXPAND_SZ ссылается на другую переменную REG_EXPAND_SZ, которая до сих пор не была расширена (буквенный порядок), эта ссылка не может быть разрешена и не расширена.
  • Когда пользователь входит в систему, обрабатывается среда пользователя.
    • То же самое REG_SZ, то REG_EXPAND_SZ обрабатываются переменные.
    • Переменные, определенные на уровне пользователя, перезаписывают значения системной среды, за исключением некоторых переменных (например, PATH), где значения объединены.

Все это означает, что может и, вероятно, будет видеть

  • Различные пользователи различных средах

  • же пользователь может видеть различные среды в зависимости от того, что родительский процесс. Нельзя использовать Win + R и выполнить cmd, чем использовать Shift + щелкните правой кнопкой мыши в папке и выберите «Открыть команду здесь». Родительские процессы разные.