Как правильно использовать SetServiceStatus, чтобы сообщить Windows, что моя служба останавливается? - PullRequest
0 голосов
/ 23 января 2012

Извините за длину образца, но чтобы получить все необходимые компоненты услуги, она должна быть такой длинной.

Используя помощь других здесь, мне удалось получить сервис, который запускается чисто, но теперь он не остановится чисто.

При первой попытке быстро остановить его выдает ошибку

Could not stop the My service service on local computer
The service did not return an error. This could be an internal Windows error or an internal service error
If the problem persists, contact your system administrator

и служба продолжает работать, даже после 5 минут, которые занимает цикл ожидания.

При второй попытке остановить диспетчер задач показывает, что процесс останавливается немедленно, но Service Manager очень долго выдает ошибку

Could not stop the My service service on local computer
Error 1053: The service did not respond to the start or control request in a timely fashion.

А вот и исходный код

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <windows.h>
#include <winsvc.h>
#include <time.h>

#define MY_SVC_NAME "My service"
#define THE_PROG "\"C:\\Program Files\\My software\\bin\\The Prog.exe\""
#define SLEEP_TIME 300000

SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;

void WINAPI ServiceMain(DWORD argc, LPSTR argv);
void WINAPI ControlHandler(DWORD request);
void InitService();


int cont_running = 1;

DWORD WINAPI ServiceHandlerProc(DWORD ControlCode, DWORD a, void *b, void *c)
{
  switch (ControlCode) {
  case SERVICE_CONTROL_STOP :
    cont_running = 0;
    ServiceStatus.dwCheckPoint=0;
    ServiceStatus.dwWin32ExitCode = 0;
    ServiceStatus.dwCurrentState  = SERVICE_STOP_PENDING;
    ServiceStatus.dwWaitHint =2000;
    SetServiceStatus (hStatus, &ServiceStatus);
    Sleep(1000);
    ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
    SetServiceStatus (hStatus, &ServiceStatus);
    break;
  case SERVICE_CONTROL_SHUTDOWN :
    cont_running = 0;
    ServiceStatus.dwCheckPoint=0;
    ServiceStatus.dwWin32ExitCode = 0;
    ServiceStatus.dwCurrentState  = SERVICE_STOP_PENDING;
    ServiceStatus.dwWaitHint =2000;
    SetServiceStatus (hStatus, &ServiceStatus);
    Sleep(1000);
    ServiceStatus.dwCurrentState  = SERVICE_STOPPED;
    SetServiceStatus (hStatus, &ServiceStatus);
    break;
  }

  return 0;

}

void WINAPI ServiceMain(DWORD argc, LPSTR argv)
{
  int hServiceStatus;

  ServiceStatus.dwServiceType        = SERVICE_WIN32;
  ServiceStatus.dwCurrentState       = SERVICE_START_PENDING;
  ServiceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
  ServiceStatus.dwWin32ExitCode      = 0;
  ServiceStatus.dwServiceSpecificExitCode = 0;
  ServiceStatus.dwCheckPoint         = 0;
  ServiceStatus.dwWaitHint           = 0;

  hServiceStatus = RegisterServiceCtrlHandlerEx(MY_SVC_NAME, ServiceHandlerProc,0);
  /*
  if (hStatus == (SERVICE_STATUS_HANDLE)0) {
    return;
  }
  */

  Sleep(1000);

  ServiceStatus.dwCheckPoint=0;
  ServiceStatus.dwWaitHint=0;
  ServiceStatus.dwCurrentState=SERVICE_RUNNING;
  SetServiceStatus( hServiceStatus, &ServiceStatus);

  InitService();

  return;
}

void InitService()
{
  cont_running=1;
  do {
    system(THE_PROG);
    Sleep(SLEEP_TIME);
  } while (cont_running);
}

int main(int argc, char *argv[], char *envp[])
{
  SERVICE_TABLE_ENTRY ServiceStartTable[2];
  ServiceStartTable[0].lpServiceName = MY_SVC_NAME;
  ServiceStartTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
  ServiceStartTable[1].lpServiceName = NULL;
  ServiceStartTable[1].lpServiceProc = NULL;


  if (!StartServiceCtrlDispatcher(ServiceStartTable))
  {
    DWORD err = GetLastError();
    if (err == ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)
      return 1;
  }

  return 0;
}

Я безуспешно ссылался на следующие документы http://msdn.microsoft.com/en-us/library/ms809975.aspx Справочное руководство по обслуживанию LUA

1 Ответ

2 голосов
/ 23 января 2012

Проблема, похоже, связана с вашей глобальной переменной SERVICE_STATUS_HANDLE hStatus: она нигде не назначена в программе, но используется несколько раз.

Кроме того, локальная переменная int hServiceStatus не делает никакихсмысл вообще.

Решение: удалите локальную переменную hServiceStatus и замените каждое использование hServiceStatus правильной переменной hStatus.

СОВЕТ: Возможно, вы уже знаете об этом, но вам следуетустановите статус STOP_PENDING только тогда, когда вы получите управляющую команду, и установите STOPPED только тогда, когда вы действительно остановили рабочий поток.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...