Dienstag, 3. Juli 2012

C++: Create a Windows service

Creating a Windows service is fairly simple. You start by writing you main() function as you would normally. In the main() function you have to call StartServiceCrtlDispatcher(). The programm has to make this call at least 30 seconds after it has launched. Otherwise Windows will assume the service failed to start up. So the simplest main() function for a service will look something like this:

int main(int argc, char **argv) {
  SERVICE_TABLE_ENTRY serviceTable[2];
  serviceTable[0].lpServiceName = "ServiceTest";
  serviceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION) ServiceMain;

  serviceTable[1].lpServiceName = NULL;
  serviceTable[1].lpServiceProc = NULL;
  StartServiceCtrlDispatcher(serviceTable);  
}

StartServiceCrtlDispatcher() takes an array of SERVICE_TABLE_ENTRYs. Each defines the name and callback function of one service it should start. The callback function is run in its own thread and StartServiceCrtlDispatcher() will only return after all services it has started have been stopped.

As the name indicates, the callback function of the service is the real main function of the service. Here the service should do whatever it is supposed to do. In order to by managed by the Services interface of Windows the service has to implement a callback to a control handler with the RegisterServiceCrtlHandler() function. The callback is invoked every time the service should change its state (Stop for example).

The service should use the SetServiceStatus() function to report its current status to the system. The following code can be used as a skeleton for your own service.

SERVICE_STATUS ServiceStatus; 
SERVICE_STATUS_HANDLE hServiceStatus; 

// Control handler function callback
void ControlHandler(DWORD request) 
{ 
  switch(request) { 
    case SERVICE_CONTROL_STOP: 
      // Service has been stopped
      ServiceStatus.dwWin32ExitCode = 0; 
      ServiceStatus.dwCurrentState  = SERVICE_STOPPED; 
      SetServiceStatus (hServiceStatus, &ServiceStatus);
      return; 
 
    case SERVICE_CONTROL_SHUTDOWN: 
      ServiceStatus.dwWin32ExitCode = 0; 
      ServiceStatus.dwCurrentState  = SERVICE_STOPPED; 
      SetServiceStatus (hServiceStatus, &ServiceStatus);
      return; 
        
    default:
      break;
  } 
 
  // Report current status
  SetServiceStatus (ServiceStatusHandle,  &ServiceStatus);
} 

// Service main function callback
void ServiceMain(int argc, char **argv) {
  int count = 0;
  int result;
 
  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= RegisterServiceCtrlHandler(
                    "ServiceTest", 
                    (LPHANDLER_FUNCTION) ControlHandler); 
  if (hServiceStatus == (SERVICE_STATUS_HANDLE) 0) { 
    // Registering Control Handler failed
    return; 
  }  

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

  while (ServiceStatus.dwCurrentState == SERVICE_RUNNING) {
    // Do you important service stuff here
    Sleep(5000);
  }
}

This service will run as long as its state is SERVICE_RUNNING. Once the state changes the ServiceMain function will return and the service will terminate.

Visit these links for more examples and explanations:



Keine Kommentare:

Kommentar veröffentlichen