Доступ к переменным окружения из служб Windows
Я пытаюсь написать службу Windows на С#. Мне нужно найти путь к определенному файлу, который хранится в переменной среды. В обычном консольном приложении С# я могу добиться этого со следующей строкой:
string t = System.Environment.GetEnvironmentVariable("TIP_HOME");
Если я пишу это на консоль, я вижу, что она прошла успешно.
Теперь, если я попробую тот же код в службе Windows, строка t
пуста.
Любая идея, почему?
Ответы
Ответ 1
Я понятия не имею, полезно ли это, но я обнаружил, что для каждой службы есть возможность добавлять переменные среды непосредственно в службу.
Это делается через реестр.
Скажите, что ключ к вашему сервису...
HKLM\SYSTEM\CurrentControlSet\Services\YourService
Создайте REG_MULTI_SZ, называемую средой.
Теперь вы можете добавлять записи, такие как...
Var1=Value1
Var2=Value2
и они будут доступны для служебного кода.
Если вы используете Windows Resource ToolKit для установки скриптов в качестве службы (instsrv.exe и srvany.exe), то, опять же, у вас есть возможность установить переменные среды для службы, но, скорее всего, это неверно один, как это было бы для srvany.exe.
Вместо этого вы используете ключ...
HKLM\SYSTEM\CurrentControlSet\Services\YourService\Параметры
и создайте REG_MULTI_SZ под названием AppEnvironment
Задайте записи таким же образом.
И теперь ваша служба script имеет собственные переменные среды.
Я использую эти методы с помощью PHP + WinCache, чтобы я мог установить APP_POOL_ID, уникальный для каждой службы, который позволяет WinCache совместно использовать центральный кеш (на основе APP_POOL_ID) для всех "потоков" (используя WShell для запуска неблокирующих дочерние "потоки" и по-прежнему используют один и тот же WinCache в качестве пусковой установки, позволяя упрощенную межпроцессную связь).
В любом случае. Надеюсь, это поможет.
Я думаю, что в основном вы не добавляете ненужные env_vars в глобальную среду. Вы можете сохранить их целевыми и уникальными, если у вас больше 1.
Привет,
Ричард.
Ответ 2
Ваша проблема кажется такой, какой мы пережили, и может быть очень сложной, чтобы понять, что происходит.
Что происходит, когда переменные среды добавляются/удаляются/меняются, среда служб не распознает это, пока не "перезапустится". Это связано с тем, что эти переменные среды хранятся в реестре, и этот реестр доступен только один раз в среде службы... при запуске системы.
Это означает, что для того, чтобы служба могла получать изменения в переменных среды, необходимо перезапустить систему.
Обратите внимание на Microsoft KB.
Ответ 3
Служба, вероятно, работает под другой учетной записью и не получает одинаковые переменные среды.
Ответ 4
Хорошо, я не совсем понимаю это, но вот что я нашел.
В той же службе я сначала попробую то, что я описал ранее, и строка возвращает пустую.
Затем, если я перечислил каждую переменную окружения на системном уровне, она найдет переменную, которую я ищу просто отлично.
Вот фрагмент кода, немного модифицированный из некоторого примера кода, найденного в 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);
}
Ответ 5
Запускаете ли вы службу под учетной записью Local System?
Перезапустили ли вы машину после добавления переменной TIP_HOME?
Службы, запущенные под локальной системой, запускаются из службы services.exe, которая только считывает свою среду при запуске: http://support.microsoft.com/kb/821761
Ответ 6
попробуйте этот код
string getsyspath = System.Environment.GetEnvironmentVariable( "TIP_HOME", EnvironmentVariableTarget.Machine);
Ответ 7
Вам нужно проверить, как была сохранена переменная.
Там метод перегрузки для Set/GetEnvironmentVariable:
Environment.GetEnvironmentVariable Method (String, EnvironmentVariableTarget)
Дело в том, что существуют три типа хранения переменной среды (EnvironmentVariableTarget):
- Машина (доступна для всех пользователей)
- Пользователь (доступен для текущего пользователя)
- Процесс (доступен только для текущего процесса [не рекомендуется кстати])
Если вы храните информацию как "Машина" или "Пользователь", вы можете протестировать ее как запуск Run (Win + R):% TIP_HOME%
Надеюсь, это поможет:)
Ответ 8
Знаете ли вы переменные среды system и пользователя? Служба Windows по умолчанию работает под учетной записью system.
Ответ 9
Я изменил эту строку кода следующим образом:
string t = System.Environment.GetEnvironmentVariable( "TIP_HOME", EnvironmentVariableTarget.Machine);
Я могу просматривать свой реестр и видеть, что TIP_HOME установлен.
Это из MSDN:
Машина: переменная среды сохраняется или извлекается из ключа HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment в реестре операционной системы Windows.
Пользовательские переменные хранятся в другом месте реестра.
Строка по-прежнему показывается пустым, когда я запускаю службу с этим изменением.
Ответ 10
Обычно службы запускаются под одной из трех учетных записей службы Local Service
Local System
и Network Service
. Для всех ваших типичных переменных окружения будет null.
Расследовать
Я тестировал, чтобы служба записывала запись журнала событий и печатала то, что она хранит в переменной HOMEPATH. Он был пустым для учетных записей службы. В С#:
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'
. Если бы вы использовали свою учетную запись пользователя, у нее был бы доступ ко всем переменным среды, к которым у вас обычно есть доступ.
.
![enter image description here]()