Registration Forgot password?
Login
Password
Remember me
Login through VKontakte
General > Articles > Writing Services for Windows with C++

Writing Tools for Windows in C++

This article is designed for people who have knowledge of programming pochatkvi

Services in Windows programs running in background, regardless of the user and usually does not interact with the user. Almost any console application can be running as a service. You need only to register it as a service. How it works (if I'm wrong please correct me somewhere), so the program starts up and begins to perform his job after work finished - service shutdown, also service must respond to signals operating system. Most services are constantly doing "hanging" in memory and periodically perform some work (eg every 5 minutes. Archive logs). In response to signals (such as stop, pause ...) the program must register the callback function. This is the main problem of the OOP for writing services as a regular class method can not register a callback function for the response to the alarm system. However, you can register the static method of class. This work established class cWinService now all the power of OOP can be used in your programming services. You have to follow your class to class and override cWinService several functions srvInit (), srvProcess (), srvStop () and your service ready to go.

For example, we will service ProcessKiller which hangs in memory and kills some process if given a start up (not all processes can be killed with user rights, as well as the service runs on as a system, it can almost all)

All source you can download with this link

process_killer.cpp


#include "stdafx.h"

#include <cProcessKiller.h>



// головна функція сервіса

int _tmain(int argc, _TCHAR* argv[])

{

  // create item of class was 

  // cProcessKiller inherited from cWinService

	cProcessKiller *killer = new cProcessKiller;

  // set global variable Service Instance

	cProcessKiller::setServiceInstance(killer);

  // run main service process

	cProcessKiller::ServiceProcess(argc, argv);

	return 0;

}

What's under the hood (comments in code)

cProcessKiller.h


#ifndef cProcessKiller_H

#define cProcessKiller_H



#include "cWinService.h"

// specific headers and constants

#include 

#include 



#define TA_FAILED 0

#define TA_SUCCESS_CLEAN 1

#define TA_SUCCESS_KILL 2

#define TA_SUCCESS_16 3



// full path to log folder

#define ZK_PATH_TO_LOG "d:\tmp\logs\";

// system service name 

#define ZK_SERVICE_NAME L"ZombieKiller";

// display service name (Win + R -> services.msc)

#define ZK_SERVICE_DISPLAY_NAME L"Zombie killer";



// inherit out class from cWinService

class cProcessKiller: public cWinService {

public:

	cProcessKiller();

	~cProcessKiller();



protected:

  // override virtual function of parent

	bool srvInit();

	bool srvProcess();

	bool srvStop();



	const char* getPathToLog();

	const LPWSTR getServiceNameL();

	const LPWSTR getServiceDNameL();

  

private:

// methods specific for task

	bool stopService();

	BOOL WaitForServiceToReachState(SC_HANDLE hService, DWORD dwDesiredState, SERVICE_STATUS* pss, DWORD dwMilliseconds);

	DWORD FindProcessId(const std::wstring& processName);

	DWORD WINAPI TerminateApp( DWORD dwPID, DWORD dwTimeout );

	static BOOL CALLBACK TerminateAppEnum(HWND hwnd, LPARAM lParam);

};

#endif

cProcessKiller.cpp


#include "stdafx.h"

#include "cProcessKiller.h"



cProcessKiller::cProcessKiller() {

	char* FullPath = getFullLogPath();

	

	Logger.setFileName(FullPath);

	Logger.setLogLevel(llDebug);

	Logger.setCode("cProcessKiller");



	delete FullPath;	

}



cProcessKiller::~cProcessKiller() {



}



// this methods is answer on virtual static function restriction

// if you know better way please give me

const LPWSTR cProcessKiller::getServiceNameL() {

	return ZK_SERVICE_NAME;

}



const LPWSTR cProcessKiller::getServiceDNameL() {

	return ZK_SERVICE_DISPLAY_NAME;

}



const char* cProcessKiller::getPathToLog() {

	return ZK_PATH_TO_LOG;

}



// in this service we no need any inticialization

// so we just return success

bool cProcessKiller::srvInit() {

	return true;

}



// "working horse" of you service

bool cProcessKiller::srvProcess() {

	return stopService();

}



// response on Windows stop request

// in this service we no need any work for stoping

// so just return success

bool cProcessKiller::srvStop() {

	return true;

}





// specific functions

bool cProcessKiller::stopService() {

	//Author: Janne Colliander

	

	bool res = true;



	DWORD dwResult = 0;



	SC_HANDLE hSCM = NULL; 

	SC_HANDLE hService = NULL;



	hSCM = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS);

	try {

		do {

			if (hSCM == NULL) {

				dwResult = GetLastError();

				Logger.writeLogHead(llError) << "OpenSCManager fail " << (int)dwResult << EndOfLine;

				break;

			}



			// Open the service 

			hService = ::OpenService(hSCM, L"Device Lock", SC_MANAGER_ALL_ACCESS/*SERVICE_STOP | SERVICE_QUERY_STATUS */);

		

			if (hService == NULL) {

				dwResult = GetLastError(); 

				Logger.writeLogHead(llError) << "OpenService fail " << (int)dwResult << EndOfLine;

				break;

			}



			//Ask the service to stop 



			SERVICE_STATUS ss;



			if(!::ControlService(hService, SERVICE_CONTROL_STOP, &ss )) {

				dwResult = GetLastError(); 



				if (dwResult != ERROR_SERVICE_NOT_ACTIVE) {

					Logger.writeLogHead(llError) << "ControlService fail " << (int)dwResult << EndOfLine;

					//break;

				}

			}





			// Wait until it stopped (or timeout expired)



			if(WaitForServiceToReachState(hService, SERVICE_STOPPED, &ss, INFINITE)) {

				Logger.writeLogHead(llError) << "WaitForServiceToReachState finish successful " << EndOfLine;

				break;

			} else {

				dwResult = GetLastError();

				Logger.writeLogHead(llError) << "WaitForServiceToReachState fail " << (int)dwResult << EndOfLine;

			}//*/



			if (DeleteService(hService)) {

				Logger.writeLogHead(llError) << "DeleteService finish successful " << EndOfLine;

				//break;

			} else {

				Logger.writeLogHead(llError) << "DeleteService fail " << (int)GetLastError() << EndOfLine;

				//break;

			}



			DWORD ProcessID = FindProcessId(L"DLService_x64.exe");

			if (ProcessID) {

				DWORD KillRes = TerminateApp(ProcessID, 3000);

				if ((KillRes == TA_SUCCESS_KILL) || (KillRes == TA_SUCCESS_CLEAN)) {

					Logger.writeLogHead(llError) << "Kill DLService_x64.exe process )" << EndOfLine;

					break;

				} else {

					Logger.writeLogHead(llError) << "Can't kill DLService_x64.exe process (" << EndOfLine;

					break;

				}

			} else {

				Logger.writeLogHead(llError) << "Can't foudn DLService_x64.exe process" << EndOfLine;

				break;

			}

		} 

		while(0);

	} catch(char* err) {

		res = false;

		Logger.writeLogHead(llError) << "stopService fail " << err << EndOfLine;

	}



	// Cleanup 



	if (hService != NULL) {

		::CloseServiceHandle(hService);

	}



	if (hSCM != NULL) {

		::CloseServiceHandle(hSCM);

	}



	// Return 

	return res;

}



BOOL cProcessKiller::WaitForServiceToReachState(SC_HANDLE hService, DWORD dwDesiredState,

                                 SERVICE_STATUS* pss, DWORD dwMilliseconds) {

	// http://www.microsoft.com/msj/0298/service.aspx

	// http://www.microsoft.com/msj/0298/servicetextfigs.htm#fig7

 

    DWORD dwLastState, dwLastCheckPoint;

    BOOL  fFirstTime = TRUE; // Don't compare state & checkpoint the first time through

    BOOL  fServiceOk = TRUE;

    DWORD dwTimeout = GetTickCount() + dwMilliseconds;

 

    // Loop until the service reaches the desired state,

    // an error occurs, or we timeout

    while  (TRUE) {

       // Get current state of service

       fServiceOk = ::QueryServiceStatus(hService, pss);

 

       // If we can't query the service, we're done

       if (!fServiceOk) break;

 

       // If the service reaches the desired state, we're done

       if (pss->dwCurrentState == dwDesiredState) break;

 

       // If we timed-out, we're done

       if ((dwMilliseconds != INFINITE) && (dwTimeout > GetTickCount())) {

          SetLastError(ERROR_TIMEOUT); 

          break;

       }

 

       // If this is our first time, save the service's state & checkpoint

       if (fFirstTime) {

          dwLastState = pss->dwCurrentState;

          dwLastCheckPoint = pss->dwCheckPoint;

          fFirstTime = FALSE;

       } else {

          // If not first time & state has changed, save state & checkpoint

          if (dwLastState != pss->dwCurrentState) {

             dwLastState = pss->dwCurrentState;

             dwLastCheckPoint = pss->dwCheckPoint;

          } else {

             // State hasn't change, check that checkpoint is increasing

             if (pss->dwCheckPoint > dwLastCheckPoint) {

                // Checkpoint has increased, save checkpoint

                dwLastCheckPoint = pss->dwCheckPoint;

             } else {

                // Checkpoint hasn't increased, service failed, we're done!

                fServiceOk = FALSE; 

                break;

             }

          }

       }

       // We're not done, wait the specified period of time

       Sleep(pss->dwWaitHint);

    }

 

    // Note: The last SERVICE_STATUS is returned to the caller so

    // that the caller can check the service state and error codes.

    return(fServiceOk);

 }



DWORD cProcessKiller::FindProcessId(const std::wstring& processName)

{

	PROCESSENTRY32 processInfo;

	processInfo.dwSize = sizeof(processInfo);



	HANDLE processesSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);

	if ( processesSnapshot == INVALID_HANDLE_VALUE )

		return 0;



	Process32First(processesSnapshot, &processInfo);

	if ( !processName.compare(processInfo.szExeFile) )

	{

		CloseHandle(processesSnapshot);

		return processInfo.th32ProcessID;

	}



	while ( Process32Next(processesSnapshot, &processInfo) )

	{

		if ( !processName.compare(processInfo.szExeFile) )

		{

			CloseHandle(processesSnapshot);

			return processInfo.th32ProcessID;

		}

	}

	

	CloseHandle(processesSnapshot);

	return 0;

}



DWORD WINAPI cProcessKiller::TerminateApp( DWORD dwPID, DWORD dwTimeout )

   {

      HANDLE   hProc ;

      DWORD   dwRet ;



      // If we can't open the process with PROCESS_TERMINATE rights,

      // then we give up immediately.

      hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, dwPID);



      if(hProc == NULL)

      {

         return TA_FAILED ;

      }



      // TerminateAppEnum() posts WM_CLOSE to all windows whose PID

      // matches your process's.

      EnumWindows((WNDENUMPROC)cProcessKiller::TerminateAppEnum, (LPARAM) dwPID) ;



      // Wait on the handle. If it signals, great. If it times out,

      // then you kill it.

      if(WaitForSingleObject(hProc, dwTimeout)!=WAIT_OBJECT_0)

         dwRet=(TerminateProcess(hProc,0)?TA_SUCCESS_KILL:TA_FAILED);

      else

         dwRet = TA_SUCCESS_CLEAN ;



      CloseHandle(hProc) ;



      return dwRet ;

   }



BOOL CALLBACK cProcessKiller::TerminateAppEnum( HWND hwnd, 

        LPARAM lParam )

    {

        DWORD dwID ;



        GetWindowThreadProcessId(hwnd, &dwID) ;



        if(dwID == (DWORD)lParam)

        {

            PostMessage(hwnd, WM_CLOSE, 0, 0) ;

        }



        return TRUE ;

    }

cWinService.h


#ifndef cWinService_H

#define cWinService_H



#include <cLog.h>

#include <windows.h>

#include <tchar.h>

#include <strsafe.h>



#define SERVICE_INSTANCE_EXP_1 "ServiceInstance not incialized"



#define WS_PATH_TO_LOG "";

#define WS_SERVICE_NAME L"ServiceInstance";

#define WS_SERVICE_DISPLAY_NAME L"Service instance";





class cWinService {

public:

	static void setServiceInstance(cWinService* Instance);

	static void ServiceProcess(int argc, TCHAR *argv[]);



protected:

	cWinService();

	~cWinService();



	virtual const char* getPathToLog();

	virtual const LPWSTR getServiceNameL();

	virtual const LPWSTR getServiceDNameL();

	SERVICE_STATUS  getStatus(); 



	// child class must override this methods

	virtual bool srvInit();

	virtual bool srvProcess();

	//bool srvStart();

	virtual bool srvStop();

	virtual bool srvPause();

	virtual bool srvContinue();



	//static cWinService* getServiceInstance();

	//static void freeServiceInstance();

	void InstallService();

	static void MainProcess();



	int ACCEPTED_CONTROL;

	int SLEEP_TIME;



	cLog Logger;

	char* getFullLogPath();



	LPWSTR ServiceName;

	LPWSTR ServiceDisplayName;



	static cWinService* ServiceInstance;

private:

	static VOID SvcReportEvent(LPTSTR szFunction, int EventID);

	static VOID WINAPI SvcCtrlHandler(DWORD dwCtrl);

	VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);



	SERVICE_STATUS          gSvcStatus; 

	SERVICE_STATUS_HANDLE   gSvcStatusHandle;	

};

#endif

cWinService.cpp


#include "stdafx.h"

#include "cWinService.h"





cWinService::cWinService() {

	ServiceName = WS_SERVICE_NAME;

	ServiceDisplayName = WS_SERVICE_DISPLAY_NAME;



	ACCEPTED_CONTROL = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;

	SLEEP_TIME = 5000;



	char* FullPath = getFullLogPath();

	

	Logger.setFileName(FullPath);

	Logger.setLogLevel(llDebug);

	Logger.setCode("cWinService");



	delete FullPath;

}



cWinService::~cWinService() {

	

}



char* cWinService::getFullLogPath() {

	char buffer[250];

	int Ln = 250 + 4;

	char* FullPath = new char[Ln];

	strcpy_s(FullPath, Ln, getPathToLog());



	char* psz = new char [wcslen(getServiceNameL()) + 1];

	wsprintfA(psz, "%S", getServiceNameL());

	concat(FullPath, Ln, psz);

	delete psz;



	time_t rawtime;

	struct tm * timeinfo;

	time(&rawtime);

	timeinfo = localtime(&rawtime);

	strftime(buffer, 30, "_%Y%m%d.log", timeinfo);

	

	concat(FullPath, Ln, buffer);



	return FullPath;

}



const char* cWinService::getPathToLog() {

	return WS_PATH_TO_LOG;

}



const LPWSTR cWinService::getServiceNameL() {

	return WS_SERVICE_NAME;

}



const LPWSTR cWinService::getServiceDNameL() {

	return WS_SERVICE_DISPLAY_NAME;

}



SERVICE_STATUS cWinService::getStatus() {

	Logger.writeLogHead(llDebug) << "invoke cWinService::getStatus " << (int)gSvcStatus.dwCurrentState << EndOfLine;

	return gSvcStatus;

}



bool cWinService::srvInit() {

	Logger.writeLogHead(llDebug) << "invoke cWinService::srvInit" << EndOfLine;

	return true;

}



bool cWinService::srvProcess() {

	Logger.writeLogHead(llDebug) << "invoke cWinService::srvProcess" << EndOfLine;

	return true;

}



/*bool cWinService::srvStart() {

	Logger.writeLogHead(llDebug) << "invoke cWinService::srvStart" << EndOfLine;

	return false;

}*/



bool cWinService::srvStop() {

	Logger.writeLogHead(llDebug) << "invoke cWinService::srvStop" << EndOfLine;

	return true;

}



bool cWinService::srvPause() {

	Logger.writeLogHead(llDebug) << "invoke cWinService::srvPause" << EndOfLine;

	return true;

}



bool cWinService::srvContinue() {

	Logger.writeLogHead(llDebug) << "invoke cWinService::srvContinue" << EndOfLine;

	return true;

}



//

// Purpose: 

//   Logs messages to the event log

//

// Parameters:

//   szFunction - name of function that failed

// 

// Return value:

//   None

//

// Remarks:

//   The service must have an entry in the Application event log.

//

VOID cWinService::SvcReportEvent(LPTSTR szFunction, int EventID) { 

	int LastErr = GetLastError();



	if (!ServiceInstance) {

		throw SERVICE_INSTANCE_EXP_1;

	}



	HANDLE hEventSource;

    LPCTSTR lpszStrings[2];

    TCHAR Buffer[80];



	hEventSource = RegisterEventSource(NULL, ServiceInstance->getServiceNameL());



    if( NULL != hEventSource ) {

        StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, LastErr);



        lpszStrings[0] = ServiceInstance->getServiceNameL();

        lpszStrings[1] = Buffer;



        ReportEvent(hEventSource,        // event log handle

                    EVENTLOG_ERROR_TYPE, // event type

                    0,                   // event category

                    EventID,			       // event identifier

                    NULL,                // no security identifier

                    2,                   // size of lpszStrings array

                    0,                   // no binary data

                    lpszStrings,         // array of strings

                    NULL);               // no binary data



        DeregisterEventSource(hEventSource);

    }

}



//

// Purpose: 

//   Sets the current service status and reports it to the SCM.

//

// Parameters:

//   dwCurrentState - The current state (see SERVICE_STATUS)

//   dwWin32ExitCode - The system error code

//   dwWaitHint - Estimated time for pending operation, 

//     in milliseconds

// 

// Return value:

//   None

//

VOID cWinService::ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) {

	Logger.writeLogHead(llDebug) << "invoke cWinService::ReportSvcStatus " << EndOfLine;



    static DWORD dwCheckPoint = 1;



    // Fill in the SERVICE_STATUS structure.



    gSvcStatus.dwCurrentState = dwCurrentState;

    gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;

    gSvcStatus.dwWaitHint = dwWaitHint;



    if (dwCurrentState == SERVICE_START_PENDING) {

        gSvcStatus.dwControlsAccepted = 0;

	} else {

		gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

	}



    if ((dwCurrentState == SERVICE_RUNNING) || (dwCurrentState == SERVICE_STOPPED)) {

        gSvcStatus.dwCheckPoint = 0;

	} else { 

		gSvcStatus.dwCheckPoint = dwCheckPoint++;

	}



    // Report the status of the service to the SCM.

    SetServiceStatus(gSvcStatusHandle, &gSvcStatus);

}





//

// Purpose: 

//   Called by SCM whenever a control code is sent to the service

//   using the ControlService function.

//

// Parameters:

//   dwCtrl - control code

// 

// Return value:

//   None

//

VOID WINAPI cWinService::SvcCtrlHandler(DWORD dwCtrl) {

	// Handle the requested control code. 

	if (!ServiceInstance) {

		throw SERVICE_INSTANCE_EXP_1;

	}

	ServiceInstance->Logger.writeLogHead(llDebug) << "cWinService::SvcCtrlHandler " << (int)dwCtrl << EndOfLine;



	// TODO add all cases

	switch(dwCtrl) {

		case SERVICE_CONTROL_STOP: 

			// Signal that service try stop

			ServiceInstance->ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);

			

			// Signal the service to stop.

			if (ServiceInstance->srvStop()) {

				ServiceInstance->gSvcStatus.dwWin32ExitCode = 0; 

				ServiceInstance->gSvcStatus.dwCurrentState = SERVICE_STOPPED; 

			} else {

				ServiceInstance->gSvcStatus.dwCurrentState = SERVICE_RUNNING;

			}

			break;



		case SERVICE_CONTROL_PAUSE: 

			// Signal that service try pause

			ServiceInstance->ReportSvcStatus(SERVICE_PAUSE_PENDING, NO_ERROR, 0);

			

			// Signal the service to pause.

			if (ServiceInstance->srvPause()) {

				ServiceInstance->gSvcStatus.dwWin32ExitCode = 0; 

				ServiceInstance->gSvcStatus.dwCurrentState = SERVICE_PAUSED;

			} else {

				ServiceInstance->gSvcStatus.dwCurrentState = SERVICE_RUNNING;

			}

			break;

 

		case SERVICE_CONTROL_CONTINUE: 

			// Signal that service try pause

			ServiceInstance->ReportSvcStatus(SERVICE_CONTINUE_PENDING, NO_ERROR, 0);

			

			// Signal the service to pause.

			if (ServiceInstance->srvContinue()) {

				ServiceInstance->gSvcStatus.dwWin32ExitCode = 0; 

				ServiceInstance->gSvcStatus.dwCurrentState = SERVICE_RUNNING;

			} else {

				ServiceInstance->gSvcStatus.dwCurrentState = SERVICE_PAUSED;

			}

			break;



		case SERVICE_CONTROL_INTERROGATE: 

			break; 

		default: 

			break;

	}

	ServiceInstance->ReportSvcStatus(ServiceInstance->gSvcStatus.dwCurrentState, NO_ERROR, 0);

}





//

// Purpose: 

//   Installs a service in the SCM database

//

// Parameters:

//   None

// 

// Return value:

//   None

//

void cWinService::InstallService() {

	SC_HANDLE schSCManager;

    SC_HANDLE schService;

    TCHAR szPath[MAX_PATH];



    if(!GetModuleFileName(NULL, szPath, MAX_PATH)) {

        printf("Cannot install service (%d)n", GetLastError());

        return;

    }



    // Get a handle to the SCM database. 

 

    schSCManager = OpenSCManager( 

        NULL,                    // local computer

        NULL,                    // ServicesActive database 

        SC_MANAGER_ALL_ACCESS);  // full access rights 

 

    if (NULL == schSCManager)  {

		int LastError = GetLastError();

        printf("OpenSCManager failed (%d)n", LastError);

		if (LastError == 5) {

			printf("please, try run with admin rightsn");

		}

        return;

    }



    // Create the service



    schService = CreateService( 

        schSCManager,			         // SCM database 

        getServiceNameL(),  // name of service 

        getServiceDNameL(), // service name to display 

        SERVICE_ALL_ACCESS,              // desired access 

        SERVICE_WIN32_OWN_PROCESS,       // service type 

        SERVICE_DEMAND_START,            // start type 

        SERVICE_ERROR_NORMAL,            // error control type 

        szPath,                          // path to service's binary 

        NULL,                            // no load ordering group 

        NULL,                            // no tag identifier 

        NULL,                            // no dependencies 

        NULL,                            // LocalSystem account 

        NULL);                           // no password 

 

    if (schService == NULL) {

        printf("CreateService failed (%d)n", GetLastError());

        CloseServiceHandle(schSCManager);

        return;

    } else {

      printf("Service installed successfullyn");

    }



    CloseServiceHandle(schService); 

    CloseServiceHandle(schSCManager);

}



/*cWinService* cWinService::getServiceInstance() {

	if (!ServiceInstance) {

		ServiceInstance = new cWinService;

	}

	return ServiceInstance;

}



void cWinService::freeServiceInstance() {

	if (ServiceInstance) {

		delete ServiceInstance;

		ServiceInstance = 0;

	}

}*/



void cWinService::setServiceInstance(cWinService* Instance) {

	if (Instance) {

		ServiceInstance = Instance;

	} else {

		ServiceInstance = 0;

	}

}



void cWinService::ServiceProcess(int argc, TCHAR *argv[]) {

    // If command-line parameter is "install", install the service. 

    // Otherwise, the service is probably being started by the SCM.



	if (!ServiceInstance) {

		throw SERVICE_INSTANCE_EXP_1;

	}



    if(lstrcmpi(argv[1], TEXT("install")) == 0) {

        ServiceInstance->InstallService();

        return;

    }



    // TO_DO: Add any additional services for the process to this table.

    SERVICE_TABLE_ENTRY DispatchTable[] = 

    { 

		{ ServiceInstance->getServiceNameL(), (LPSERVICE_MAIN_FUNCTION)cWinService::MainProcess}, 

        { NULL, NULL } 

    }; 

 

    // This call returns when the service has stopped. 

    // The process should simply terminate when the call returns.

    if (!StartServiceCtrlDispatcher(DispatchTable)) {

        cWinService::SvcReportEvent(TEXT("StartServiceCtrlDispatcher"), 1);

    }

}



void cWinService::MainProcess() {

	if (!ServiceInstance) {

		throw SERVICE_INSTANCE_EXP_1;

	}



	ServiceInstance->Logger.writeLogHead(llError) << "cWinService::MainProcess started" << EndOfLine;



	ServiceInstance->gSvcStatus.dwServiceType        = SERVICE_WIN32; 

  ServiceInstance->gSvcStatus.dwCurrentState       = SERVICE_START_PENDING; 

  ServiceInstance->gSvcStatus.dwControlsAccepted   = ServiceInstance->ACCEPTED_CONTROL;

  ServiceInstance->gSvcStatus.dwWin32ExitCode      = 0; 

  ServiceInstance->gSvcStatus.dwServiceSpecificExitCode = 0; 

  ServiceInstance->gSvcStatus.dwCheckPoint         = 0; 

  ServiceInstance->gSvcStatus.dwWaitHint           = 0; 

 



	ServiceInstance->gSvcStatusHandle = RegisterServiceCtrlHandler(ServiceInstance->getServiceNameL(), (LPHANDLER_FUNCTION)cWinService::SvcCtrlHandler); 

    if (!ServiceInstance->gSvcStatusHandle) { 

		ServiceInstance->Logger.writeLogHead(llError) << "Registering Control Handler failed" << EndOfLine;

        return;

    }



    // Initialize Service 

    if (!ServiceInstance->srvInit()) {

		ServiceInstance->Logger.writeLogHead(llError) << "Initialization failed" << EndOfLine;

		ServiceInstance->gSvcStatus.dwCurrentState       = SERVICE_STOPPED; 

        ServiceInstance->gSvcStatus.dwWin32ExitCode      = -1; 

        SetServiceStatus(ServiceInstance->gSvcStatusHandle, &(ServiceInstance->gSvcStatus));

        return; 

    } 

    // We report the running status to SCM. 

    ServiceInstance->gSvcStatus.dwCurrentState = SERVICE_RUNNING; 

    SetServiceStatus (ServiceInstance->gSvcStatusHandle, &(ServiceInstance->gSvcStatus));

 

    // The worker loop of a service

    while (ServiceInstance->gSvcStatus.dwCurrentState == SERVICE_RUNNING)

	{

		if (!ServiceInstance->srvProcess()) {

			ServiceInstance->gSvcStatus.dwCurrentState       = SERVICE_STOPPED; 

			ServiceInstance->gSvcStatus.dwWin32ExitCode      = -1; 

			SetServiceStatus(ServiceInstance->gSvcStatusHandle, &(ServiceInstance->gSvcStatus));

			return;

		}



		Sleep(ServiceInstance->SLEEP_TIME);

	}

}



cWinService* cWinService::ServiceInstance = 0;

You can add comment on current page, or on forum page there.Post count 7.

Last comment

13.07.2016
Great ingtshi! That's the answer we've been looking for. http://epvwjsr.com [url=http://dygcymujjd.com]dygcymujjd[/url] [link=http://kedpjto.com]kedpjto[/link]
11.07.2016
An inlgelitent answer - no BS - which makes a pleasant change
10.07.2016
I read your post and wisehd I was good enough to write it http://khbzet.com [url=http://nygnoc.com]nygnoc[/url] [link=http://vthcqyznti.com]vthcqyznti[/link]

Name*E-mail
Code*