четверг, 17 сентября 2009 г.

Ошибка 1053. Сервисы на Windows 7

Наткнулся недавно на любопытный баг. Переносил группу проектов с Delphi 2007 на Delphi 2010. С параллельным переходом на Windows 7. Да, знаю, нельзя менять сразу все, но.. так получилось :)

Проекты - группа сервисов. Баг выразился следующим образом. Запускаю любой (один!) сервис - все в порядке. Пытаюсь запустить любой второй - вылетает ошибка "Error 1053: The service did not respond to the start or control request in a timely fashion". Самое неприятное - ошибка вылетает немедленно, сразу при запуске сервиса. Все попытки поставить в ServiceStart Sleep(пара минут) и следом бряк ничего не дали - ошибка вылетает раньше, до того, как выполнится ServiceStart.

Правда, один сервис работал корректно и никак не мешал запуску других сервисов. Сравнил - выяснил, что все проблемные сервисы использовали Indy. Точнее, класс TIdHTTPServer. А тот сервис, что работал корректно, этот класс не использовал и с Indy никак связан не был. Поискал в интернете - нашел описание подобной проблемы на форуме Embarcadero. Правда, решения там не оказалось.

Проблема решилась на следующий день на удивление просто. Создал новый сервис. Визард написал следующий код в файле проекта:

begin
// Windows 2003 Server requires StartServiceCtrlDispatcher to be
// called before CoRegisterClassObject, which can be called indirectly
// by Application.Initialize. TServiceApplication.DelayInitialize allows
// Application.Initialize to be called from TService.Main (after
// StartServiceCtrlDispatcher has been called).
//
// Delayed initialization of the Application object may affect
// events which then occur prior to initialization, such as
// TService.OnCreate. It is only recommended if the ServiceApplication
// registers a class object with OLE and is intended for use with
// Windows 2003 Server.
//
// Application.DelayInitialize := True;
//
if not Application.DelayInitialize or Application.Installing then
Application.Initialize;
Application.CreateForm(TService1, Service1);
Application.Run;
end.
Проверил - все нерабочие сервисы отложенную инициализацию не использовали. Заменил "Application.Initialize;" на

Application.DelayInitialize := True;
if not Application.DelayInitialize or Application.Installing then begin
Application.Initialize;
end;
и все заработало.