Здравствуйте, flatline, Вы писали:
F>skipped
Недавно наткнулся на такие грабли: Win7, default настройки безопасности. Сервис хостит сторонний COM-объект и запускается от Local System. При старте сервиса вызывается один из методов COM-объекта, после чего сервис намертво виснет. Код из OnStart() сервиса был перенесен в консольное приложение. Было обнаружено, что при вызове этого метода срабатывает брандмауэр с соответствующей выдачей диалогового окна. Пришлось добавлять разрешение в конфигурацию брандмауэра руками...
Остался вопрос, какого выдается окно, можно же определить, что это ни разу не интерактивный сервис... но, думаю, что он риторический...
Проверьте, на всякий случай.
В общем, проблема в подписи исполняемого файла службы.
Подписываю следующим образом.
signtool.exe sign /f <name>.pfx /p <pass> <file>
Далее, при помощи 'sc', производится обычная инсталляция этого файла в качестве службы.
Итог — если файл подписан, то каждый раз при ручном запуске службы (через интерфейс или командную строку) происходит следующее:
1. Процесс появляется в списке.
2. Система что-то долго делает.
3. Происходит вызов Main/OnStart.
4. Служба успешно запущена.
Если идёт автозапуск, то всё завершается на п.2, по таймауту видимо.
Если исполняемый файл службы не подписан, то никаких задержек при старте не происходит. И автозапуск и ручной запуск проходят быстро и без ошибок.
Здравствуйте, flatline, Вы писали:
F>Если исполняемый файл службы не подписан, то никаких задержек при старте не происходит. И автозапуск и ручной запуск проходят быстро и без ошибок.
Самое забавное, что полтора месяца назад такая проблема уже всплывала
Проявляется только на W7, на любых. Системы чистые (и реальные и под VM). Под 2003/XP проблема не повторяется.
Есть два проекта под .NET 2.0 — один реальный, второй тестовый (код ниже). Тестовый изначально был минимальным сервисом (дефолтный проект, созданный из под VS2008). В реальном проекте основную часть довёл до минимума в процессе тестов. Т.е. на данный момент он при запуске выполняет полностью то же самое, что и тестовый (хотя, судя по описанному ниже поведению, видимо нет). В реальном проекте используются классы из 'System.Net.Sockets' и 'System.Data.SqlClient'. Но вся инициализация, связанная с ними, для тестов была убрана и из Main и из OnStart.
Оба сервиса регистрируются на тестовой машине при помощи SC.
sc create <имя> binpath= <путь> type= own start= auto
Строка 'if (args.Length == 0)' в 'Main' добавлена в тестовых целях, что бы в случае запуска с параметром командной строки, экзешник отрабатывал в холостую.
Далее, у тестового сервиса наблюдается абсолютно нормальное поведение и при ручном запуске/остановке и при автоматическом старте при запуске системы и при холостом запуске с параметром командной строки.
У реального проекта симптомы мне не понятные:
1. Если в системе включена (не Disabled) служба "WinHttpAutoProxySvc", то если запустить экзешник сервиса любым способом (и как службу и в холостом режиме через командную строку), он зачем-то выполняет запуск указанной выше службы, что-то от неё ожидает, мучается секунд 20-30, потом успешно завершается (если в холостом режиме) или переходит в режим "работает" (если как служба).
2. Если служба 'WinHttpAutoProxySvc' в состоянии 'Disabled', то в обоих случаях запуск отрабатывает мгновенно.
3. При автозапуске при загрузке системы мой сервис не стартует вообще (независимо от наличия 'WinHttpAutoProxySvc'). В событиях системы появляется надпись "служба не ответила на запрос своевременно". Я пробовал ставить протоколирование на входе в 'Main' и 'OnStart', но эти участки почему-то не отрабатывают вообще.
Все статические объекты (коих мало и все мне известны) инициализируются только явно. Т.е. в коде нет участков типа 'static MyClass obj = new MyClass()', а любая работа из 'Main' и 'OnStart' убрана.
В какую сторону вообще смотреть? Проблема конечно обходимая, но неудобства создаёт на клиентских машинах.
P.S.: гуглил, Рихтера читал, ещё одну книгу по практике тоже, но причин оного поведения так и не смог понять.
static void Main(string[] args)
{
if (args.Length == 0)
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new TestService() };
ServiceBase.Run(ServicesToRun);
}
}
public partial class TestService : ServiceBase
{
public TestService()
{
InitializeComponent();
}
protected override void OnStart(string[] args) { }
protected override void OnStop() { }
}
Файрвол — первое на что были подозрения. Но при любых его настройках поведение службы при старте системы одинаковое — "не ответила своевременно". При ручном старте — запускается. К тому же, на данный момент у проблемного сервиса в OnStart пусто, а в Main присутствует только код для инициализации сервиса.
Сейчас, для теста, собрал этот проект для запуска как приложения. Проект тот же, просто в 'Main' под #ifdef был добавлен код на загрузку формы.
#if START_AS_APP
Application.Run(new MainForm());
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new MainService() };
ServiceBase.Run(ServicesToRun);
#endif
На самой форме кнопки 'start/stop', которые выполняют то же самое, что и 'OnStart/OnStop' сервиса. На любой W7 машине запускается/выгружается моментально и 'start/stop' отрабатывает без задержек. Требуемые задачи выполняет.
И выявилось странное обстоятельство со службой 'WinHttpAutoProxySvc':
1. Если экзешник собран как служба и зарегистрирован в системе (запущена служба или не не важно), то его запуск в холостом режиме, т.е. когда он ничего не делает в Main и сразу завершается, странным образом зависит от этой самой 'WinHttpAutoProxySvc'. Т.е. он её мучает достаточно долго.
2. Если экзешник в системе как служба не зарегистрирован, то любые запуски экзешника проходят без каких либо задержек, независимо от состояния 'WinHttpAutoProxySvc'.
При регистрации службы я совершенно точно не указываю никаких зависимостей, в информации о службе оных тоже не видно.
Видимо, невнимательно я литературу читал. Источник проблемы выявил, но причин пока не понимаю.
Сервис в своей работе использует дополнительную сборку common.dll, которую я инсталлирую в тот же каталог, что и основной файл сервиса. Так вот при автостарте на этапе запуска системы служба почему-то не может подгрузить этот модуль. Если скомпилировать всё внутрь исполнимого файла сервиса, то все проблемы разрешаются.
Служба "WinHttpAutoProxySvc", по всей видимости, используется на том этапе, когда производится попытка отыскать common.dll, в т.ч. и на сетевых ресурсах.
P.S.: осталось понять, как правильно расположить/прописать common.dll, т.к. компилировать его внутрь не очень удобно.
F>>Если исполняемый файл службы не подписан, то никаких задержек при старте не происходит. И автозапуск и ручной запуск проходят быстро и без ошибок. S>Самое забавное, что полтора месяца назад такая проблема уже всплывала