Содержание материала

StartServiceCtrlDispatcher выполнится только после того, как все сервисы будут остановлены.

 

Функция LogError протоколирует ошибки - напишите ее сами.

Функция ServiceMain        

ServiceMain - основная функция сервиса. Если в ехешнике несколько сервисов, но для каждого сервиса пишется своя ServiceMain функция. Имя функции может быть любым! и передается в DispatchTable.lpServiceProc:=@ServiceMain (см.предыдущущий абзац). У меня она называется ServiceProc и описывается так:

procedure ServiceProc(argc : DWORD;var argv : array of PChar);stdcall;

argc кол-во аргументов и их массив argv передаются менеджером сервисов из настроек сервиса. НЕ ЗАБЫВАЙТЕ STDCALL!!! Такая забывчивость - частая причина ошибки в программе.

 

В ServiceMain требуется выполнить подготовку к запуску сервиса и зарегистрировать обработчик сообщений от менеджера сервисов (Handler). Опять после запуска ServiceMain и до запуска RegisterServiceCtrlHandler должно пройти минимум времени. Если сервису надо делать что-нибудь очень долго и обязательно до вызова RegisterServiceCtrlHandler, то надо посылать сообщение SERVICE_START_PENDING функией SetServiceStatus.

 

Итак, в RegisterServiceCtrlHandler передаем название нашего сервиса и адрес функции Handler'а (см.далее). Далее выполняем подготовку к запуску и настройку сервиса. Остановимся на настройке поподробнее.

Эта самая настройка var ServiceStatus : SERVICE_STATUS;

(ServiceStatusHandle : SERVICE_STATUS_HANDLE и ServiceStatus надо сделать глобальными переменными и поместить их выше всех функций).

 

dwServiceType - тип сервиса

 

 

SERVICE_WIN32_OWN_PROCESS

Одиночный сервис

 

SERVICE_WIN32_SHARE_PROCESS

Несколько сервисов в одном процессе

 

SERVICE_INTERACTIVE_PROCESS

интерактивный сервис (может взаимодействовать с пользователем).

 

Остальные константы - о драйверах. Если надо - смотрите их в MSDN.

 

dwControlsAccepted - принимаемые сообщения (какие сообщения мы будем обрабатывать)                

SERVICE_ACCEPT_PAUSE_CONTINUE        приостановка/перезапуск        

SERVICE_ACCEPT_STOP        остановка сервиса        

SERVICE_ACCEPT_SHUTDOWN        перезагрузка компьютера        

SERVICE_ACCEPT_PARAMCHANGE        изменение параметров сервиса без перезапуска (Win2000 и выше)        

Остальные сообщения смотрите опять же в MSDN (куда уж без него ;-)

 

dwWin32ExitCode и dwServiceSpecificExitCode - коды ошибок сервиса. Если все идет нормально, то они должны быть равны нулю, иначе коду ошибки.

 

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

 

dwWaitHint - время, через которое сервис должен послать свой новый статус менеджеру сервисов при выполнении действия (запуска, остановки и т.д.). Если dwCurrentState и dwCheckPoint через это кол-во миллисекунд не изменится, то менеджер сервисов решит, что произошла ошибка.

 

dwCurrentState - см. где-то здесь Ставим его в SERVICE_RUNNING, если сервис запущен

 

После заполнения этой структуры посылаем наш новый статус функцией SetServiceStatus и мы работаем :).

 

После этого пишем код самого сервиса. Я вернусь к этому попозже.

Вот так выглядит моя ServiceMain :

Code:

procedure ServiceProc(argc : DWORD;var argv : array of PChar);stdcall;

var

Status : DWORD;

SpecificError : DWORD;

begin

ServiceStatus.dwServiceType      := SERVICE_WIN32;

ServiceStatus.dwCurrentState     := SERVICE_START_PENDING;

ServiceStatus.dwControlsAccepted := SERVICE_ACCEPT_STOP

   or SERVICE_ACCEPT_PAUSE_CONTINUE;

ServiceStatus.dwWin32ExitCode           := 0;

ServiceStatus.dwServiceSpecificExitCode := 0;

ServiceStatus.dwCheckPoint              := 0;

ServiceStatus.dwWaitHint                := 0;

 

ServiceStatusHandle :=

          RegisterServiceCtrlHandler(ServiceName,@ServiceCtrlHandler);

if ServiceStatusHandle = 0 then WriteLn('RegisterServiceCtrlHandler Error');

 

Status :=ServiceInitialization(argc,argv,SpecificError);

if Status <> NO_ERROR

  then begin

   ServiceStatus.dwCurrentState := SERVICE_STOPPED;

   ServiceStatus.dwCheckPoint   := 0;

   ServiceStatus.dwWaitHint     := 0;

   ServiceStatus.dwWin32ExitCode:=Status;

   ServiceStatus.dwServiceSpecificExitCode:=SpecificError;

 

   SetServiceStatus (ServiceStatusHandle, ServiceStatus);

       LogError('ServiceInitialization');

   exit;

  end;

 

  ServiceStatus.dwCurrentState :=SERVICE_RUNNING;

  ServiceStatus.dwCheckPoint   :=0;

  ServiceStatus.dwWaitHint     :=0;

 

  if not SetServiceStatus (ServiceStatusHandle,ServiceStatus)

   then begin

    Status:=GetLastError;

        LogError('SetServiceStatus');

    exit;

   end;

// WORK HERE

//ЗДЕСЬ БУДЕТ ОСНОВНОЙ КОД ПРОГРАММЫ

end;

 

 

Добавить комментарий

Не использовать не нормативную лексику.

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

ВСЕ КОММЕНТАРИИ МОДЕРИРУЮТСЯ ВРУЧНУЮ, ТАК ЧТО СПАМИТЬ БЕСПОЛЕЗНО!


Защитный код
Обновить