Доступ к переменным среды из служб Windows

Я пытаюсь написать службу Windows на C #. Мне нужно найти путь к определенному файлу, который хранится в переменной окружения. В обычном консольном приложении C # я могу добиться этого с помощью следующей строки:

string t = System.Environment.GetEnvironmentVariable("TIP_HOME");

Если я напишу это в консоль, я увижу, что все прошло успешно.

Теперь, если я попробую тот же код в службе Windows, строка t будет пустой.

Есть идеи, почему?


person Brian    schedule 20.11.2008    source источник


Ответы (10)


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

Это делается через реестр.

Скажите, что ключ к вашим услугам ...

HKLM \ SYSTEM \ CurrentControlSet \ Services \ YourService

Создайте REG_MULTI_SZ под названием Environment.

Теперь вы можете добавлять такие записи, как ...

Var1=Value1
Var2=Value2

и они будут доступны по сервисному коду.

Если вы используете Windows Resource ToolKit для установки скриптов как службы (instsrv.exe и srvany.exe), то, опять же, у вас есть возможность установить переменные среды для службы, но, скорее всего, это неправильная будет для srvany.exe.

Вместо этого вы используете ключ ...

HKLM \ SYSTEM \ CurrentControlSet \ Services \ YourService \ Parameters

и создайте REG_MULTI_SZ под названием AppEnvironment

Таким же образом установите записи.

И теперь ваша служба сценариев имеет собственные переменные среды.

Я использую эти методы с PHP + WinCache, чтобы позволить мне установить APP_POOL_ID, уникальный для каждой службы, что позволяет WinCache совместно использовать центральный кеш (на основе APP_POOL_ID) для всех «потоков» (используя WShell для запуска неблокирующих дочерних потоков) "и по-прежнему использовать тот же WinCache, что и средство запуска, что позволяет упростить взаимодействие между процессами).

Так или иначе. Надеюсь, это немного поможет.

Я думаю, что в основном вы не добавляете ненужные env_vars в глобальную среду. Вы можете сделать их целевыми и уникальными, если у вас их больше одного.

С уважением,

Ричард.

person Richard Quadling    schedule 28.04.2010
comment
Здорово! Действительно полезное замечание! Собираюсь использовать это в своем проекте. - person Igor Malin; 10.11.2011

Кажется, ваша проблема похожа на нашу, и может быть очень сложно понять, что происходит.

Что происходит, когда переменные среды добавляются / удаляются / изменяются, среда служб не распознает это до тех пор, пока не будет "перезапущена". Это связано с тем, что эти переменные среды хранятся в реестре, и этот реестр читается только один раз средой службы ... при запуске системы.

Это означает, что для того, чтобы служба зафиксировала изменение переменных среды, необходимо перезапустить систему.

Прочтите об этом Microsoft KB.

person Scott Saad    schedule 20.11.2008
comment
Но обратите внимание, что это верно только для служб, работающих под локальной системной учетной записью. Для служб, работающих под указанной учетной записью пользователя, они будут получать изменения среды из реестра после перезапуска. - person Martin Ba; 30.06.2011

Служба, вероятно, работает под другой учетной записью и не получает те же переменные среды.

person EBGreen    schedule 20.11.2008
comment
Думаю, мне следовало это пояснить, но TIP_HOME - системная переменная. Я думал, что системные переменные НЕ зависят от пользователя? - person Brian; 20.11.2008
comment
Что ж, в качестве теста вы можете добавить отладочный код в свою службу, чтобы он перебирал все переменные среды, которые он видит при запуске, и выводил их во временный файл. - person EBGreen; 20.11.2008

Вы запускаете службу под учетной записью локальной системы?

Вы перезагружали компьютер после добавления переменной TIP_HOME?

Службы, работающие в локальной системе, запускаются из службы services.exe, которая считывает свою среду только при запуске: http://support.microsoft.com/kb/821761

person Michael Burr    schedule 20.11.2008
comment
Да, машина была перезапущена, так как была установлена ​​системная переменная. Я создаю и запускаю сервис под учетной записью администратора. - person Brian; 20.11.2008

Ладно, я этого не совсем понимаю, но вот что я нашел ...

В той же службе я сначала пробую то, что описал ранее, и строка возвращает пустую.

Затем, если я перебираю каждую из переменных среды системного уровня, он прекрасно находит переменную, которую я ищу.

Вот фрагмент кода, немного измененный по сравнению с образцом кода, найденным в MSDN:

foreach(DictionaryEntry de in Environment.GetEnvironmentVariables(tgt))
{
    key   = (string)de.Key;
    value = (string)de.Value;

    if(key.Equals("TIP_HOME") && value != null)
        log.WriteEntry("TIP_HOME="+value, EventLogEntryType.Information);
}
person Brian    schedule 20.11.2008

попробуйте эту строку кода getsyspath = System.Environment.GetEnvironmentVariable ("TIP_HOME", EnvironmentVariableTarget.Machine);

person MANASA    schedule 15.10.2009


Службы обычно запускаются под одной из трех учетных записей служб, Local Service Local System и Network Service. Для всех этих случаев ваша типичная переменная среды будет нулевой.


Для расследования


Я протестировал, заставив службу записать запись в журнал событий и распечатать то, что она хранит, в переменной HOMEPATH. Для учетных записей служб он вернулся пустым. В C #:

protected override void OnStart(string[] args)
{
    EventLog.WriteEntry("The HomePath for this service is '" + Environment.GetEnvironmentVariable("HOMEPATH") + "'", EventLogEntryType.Information);
}

Возможные решения


Вы можете указать, какую учетную запись использует служба (например, ваша учетная запись пользователя), в окне свойств служб или в конфигурации установки службы. Когда я тестировал свою учетную запись пользователя, в журнале событий отображалось The HomePath for this service is '\Users\Admin-PC'. Если бы он использовал вашу учетную запись пользователя, у него был бы доступ ко всем переменным среды, к которым у вас обычно есть доступ.
введите описание изображения здесь. введите описание изображения здесь

person Joseph    schedule 21.03.2015

Знаете ли вы о переменных среды system и user? Служба Windows по умолчанию работает под учетной записью system.

person Steve Dunn    schedule 20.11.2008
comment
Да, переменная, которую я ищу, является системной переменной. См. Ответ, который я опубликовал ниже. - person Brian; 20.11.2008

Я изменил эту строку кода на это:

строка t = System.Environment.GetEnvironmentVariable ("TIP_HOME", EnvironmentVariableTarget.Machine);

Я могу просмотреть свой реестр и увидеть, что TIP_HOME установлен.

Это из MSDN: Machine: переменная среды хранится или извлекается из раздела HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Control \ Session Manager \ Environment в реестре операционной системы Windows.

Пользовательские переменные хранятся в другом месте реестра.

Тем не менее, строка все еще отображается пустой, когда я запускаю службу с этим изменением.

person Brian    schedule 20.11.2008
comment
Вы пытались перечислить env vars, как я предлагал? - person EBGreen; 20.11.2008
comment
Я пытаюсь понять, как ... Я новичок в C #, и он мне нужен только для этого крошечного проекта. - person Brian; 20.11.2008