Доступ к переменным среды из служб Windows
Я пытаюсь написать службу Windows на C#. Мне нужно найти путь к определенному файлу, который хранится в переменной окружения. В обычном консольном приложении C# я могу добиться этого с помощью следующей строки:
string t = System.Environment.GetEnvironmentVariable("TIP_HOME");
Если я напишу это в консоль, я увижу, что это было успешно.
Теперь, если я попробую тот же код в службе Windows, строка t
пустой.
Есть идеи почему?
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 \ Параметры
и создайте REG_MULTI_SZ с именем AppEnvironment
Установите записи таким же образом.
И теперь у вашего скриптового сервиса есть свои собственные переменные окружения.
Я использую эти методы с PHP+WinCache, чтобы позволить мне установить APP_POOL_ID, уникальный для каждого сервиса, который позволяет WinCache совместно использовать центральный кеш (на основе APP_POOL_ID) для всех "потоков" (используя WShell для запуска неблокирующих дочерних "потоков" "и все еще используют тот же WinCache, что и модуль запуска, что позволяет упростить межпроцессное взаимодействие).
Тем не мение. Надеюсь, это поможет несколько.
Я думаю, что в основном вы не добавляете ненужные env_vars в глобальную среду. Вы можете оставить их целевыми и уникальными, если их больше 1.
С Уважением,
Ричард.
Ваша проблема, кажется, что-то вроде того, что мы испытали, и может быть очень сложно выяснить, что происходит.
Что происходит, когда переменные среды добавляются / удаляются / изменяются, среда служб не распознает это, пока не "перезапустится". Это связано с тем, что эти переменные среды хранятся в реестре, и этот реестр читается сервисной средой только один раз... при запуске системы.
Это означает, что для того, чтобы служба восприняла изменение переменных среды, необходимо выполнить перезагрузку системы.
Проверьте Microsoft KB на этом.
Служба, вероятно, работает под другой учетной записью и не получает одинаковые переменные среды.
Вы запускаете службу под учетной записью локальной системы?
Вы перезапустили компьютер после добавления переменной TIP_HOME?
Службы, работающие в локальной системе, запускаются из службы services.exe, которая считывает свою среду только при запуске: http://support.microsoft.com/kb/821761
Знаете ли вы о системных и пользовательских переменных среды? Служба Windows по умолчанию работает под системной учетной записью.
Службы обычно работают под одной из трех учетных записей служб, 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'
, Если бы он использовал вашу учетную запись, он имел бы доступ ко всем переменным среды, к которым у вас обычно есть доступ.
,
Вам нужно проверить, как хранилась переменная. Есть метод перегрузки для Set / GetEnvironmentVariable:
Environment.GetEnvironmentVariable Метод (String, EnvironmentVariableTarget)
Дело в том, что существует три типа хранения переменной среды ( EnvironmentVariableTarget):
- Машина (доступна для всех пользователей)
- Пользователь (доступно для текущего пользователя)
- Процесс (доступно только для текущего процесса [не рекомендуется)
Если вы храните информацию как "Машина" или "Пользователь", вы можете проверить ее как выполняющуюся "Выполнить" (Win + R): %TIP_HOME%
Надеюсь, поможет:)
Попробуйте эту строку кода getsyspath = System.Environment.GetEnvironmentVariable("TIP_HOME",EnvironmentVariableTarget.Machine);
Хорошо, я не совсем понимаю это, но вот что я нашел..
В том же сервисе я сначала пробую то, что описал ранее, и строка возвращается пустой.
Затем, если я перечислю все переменные окружения системного уровня, он найдет нужную переменную.
Вот фрагмент кода, слегка измененный из некоторого примера кода, найденного в 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);
}
Я изменил эту строку кода для этого:
строка t = System.Environment.GetEnvironmentVariable("TIP_HOME", EnvironmentVariableTarget.Machine);
Я могу просмотреть свой реестр и убедиться, что TIP_HOME установлен.
Это из MSDN: Machine: переменная среды хранится или извлекается из ключа HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment в реестре операционной системы Windows.
Пользовательские переменные хранятся в другом месте в реестре.
Тем не менее, строка все еще отображается пустой, когда я запускаю службу с этим изменением.