65.9K
CodeProject is changing. Read more.
Home

A general purpose NT Service Class

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.59/5 (18 votes)

Jul 7, 2004

CPOL

2 min read

viewsIcon

62278

downloadIcon

3102

Build a NT Service

Introduction

Apologies in advance about my English and the brief descriptions, as my native language is German. The TService class wraps all the things around a NT-Service and allows to create a NT-Service with a few lines of code.

TService

virtual void ServiceProc           (void) = PURE;

This is the main service procedure. If you leave ServiceProc() your service is stopped.

virtual const char* GetName        (void) = PURE;
virtual const char* GetDisplayName (void) {return GetName();}

Simply return a string to identify the service by name. You can also overwrite the GetDisplayName() procedure to install your service with a different display name.

bool          Execute        (void);

Run as Service. This should be the default call for your service from the main procedure.

bool          ConsoleMode    (void);

To check out a service you can run the service from a console window. The service runs in the logged on user account.

bool          Start          (void);
bool          Stop           (void);
bool          Install        (void);
bool          Remove         (void);
virtual bool  Help           (DWORD context = 0);

Control the service. Help() searches for a helpfile named "GetName().hlp"

bool          Terminated     (void;}
void          Terminate      (void;}

Your ServiceProc() must check Terminated() periodically to get a stop request. When Terminated() returns true you should leave the ServiceProc() und cleanup your Service. Call Terminate() to stop the Service from outside ServiceProc().

const char *  LastError      (void)  const {return m_ServiceError;}

Returns the last error as string from the system.

void          PrintLastError   (const char *Caption = NULL);

Writes the last error to the standard error device if any.

bool SetConfigValue (char* key,BYTE *value,DWORD nvalue,cfValType type = cfString);
bool GetConfigValue (char* key,BYTE *buf,DWORD *nbuff,cfValType *ypet);

    enum cfValType {
      cfBinary  = REG_BINARY,
      cfDword   = REG_DWORD,
      cfString  = REG_S
    };

Set and get Registry Values like RegSetValue() and RegQueryValue(). The values are located under : "HKLM\SYSTEM\CurrentControlSet\Services\%ServiceName%\ServiceConfig\".

void LogEvent       (char* event,evLogType type = evInfo,WORD category = 0);

   enum evLogType {
      evError   = EVENTLOG_ERROR_TYPE,
      evWarning = EVENTLOG_WARNING_TYPE,
      evInfo    = EVENTLOG_INFORMATION_TYPE
   };

Write to the SystemEventLog.

virtual bool Init             (void)       {return true;}

Is be called before ServiceProc(), you can setup your service here. If Init() returns false the service will stop.

virtual void Cleanup          (void)       {return;}

The service is stopped, cleanup resources from Init().

virtual void LogoffEvent      (void)       {return;}

A user has logged off. If you would check that a user is logged in search in ServiceProc() for a window named "Shell_TrayWnd".

virtual void ShutdownEvent    (void)       {Terminate();}

The Machine is shutting down, terminate the service.

Sample

Here is a short quick and dirty sample how to create a service. To control the service run the executable from the console with the parameters :

/install to install the service
/remove to remove the service from the system
/start to start the service
/quit to stop the service
/test

to test the service from a console window

#include "cService.hpp" // cService.h AND cService.cpp

class  cMyService : private TService {
 public:
   cMyService (char *arg);

 private:
   const char* GetName        (void){return "MyService";}
   void        ServiceProc    (void);
};

cMyService::cMyService (char *arg) {
if (arg != NULL) {
  unsigned short a = *((unsigned short*) arg);  

   if      (a == *((unsigned short*) "/i")) Install(); 
   else if (a == *((unsigned short*) "/r")) Remove();
   else if (a == *((unsigned short*) "/s")) Start();
   else if (a == *((unsigned short*) "/q")) Stop();
   else if (a == *((unsigned short*) "/t")) ConsoleMode();
   }
else Execute();
}

void cMyService::ServiceProc (void) {
while (! Terminated()) {
   Beep  (400,100);
   Sleep (5000);
   }
}

void main (int argc,char *argv[]) {
delete new cMyService(argv[1]);
}

History

  • July 7, 2004 - First release.