Регистрация Забыли пароль?
Логин
Пароль
Запомнить меня
Вход через ВКонтакте
Главная > Статьи > Как написать сервис для Windows на C++

Как написать сервис для Windows на C++

Данная статья рассчитана на людей имеющих начальное знание программирования

Сервисы в Windows программы, выполняются в фоне, независимо от пользователя и обычно никак с пользователем не взаимодействуют. Почти любую консольную парограму можно выполнить как сервис. Для этого нужно только зарегистрировать ее как сервис. Как все работает (если я где-то ошибся поправьте меня), следовательно программа запускается и начинает выполнять какую-то свою работу после завершения работы сервис останавливается и заканчивает выполнение, также сервис должен реагировать на сигналы операционной системы. Чаще всего делают сервисы постоянно "висят" в памяти и время от времени выполняют какую-то работу (например раз в 5 мин. архивируют логи). Для реакции на сигналы системы (такие как стоп, пауза ...) программа должна зарегистрировать callback функции. В этом заключается основная проблема использования ООП для написания сервисов так как обычный метод класса нельзя зарегистрировать как callback функция для реакции на сигнал системы.Однако можно зарегистрировать статический метод класса. На этом основана работа класса cWinService теперь вся мощь ООП может быть использована вами в программировании сервисов. Вам достаточно следовать ваш класс от класса cWinService и переопределить несколько функций srvInit(), srvProcess(), srvStop() и ваш сервис готов к работе.

Для примера возьмем сервис ProcessKiller который висит в памяти и убивает заданный процесс если он запустился (не все процессы можно убить с правами, а так как сервис запускается с правами системы, он может практически все)

Все исходники можно скачать по этой ссылке

process_killer.cpp


#include "stdafx.h"

#include <cProcessKiller.h>



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

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

{

  // создаем екземпляр класа который

  // cProcessKiller наследован от cWinService

	cProcessKiller *killer = new cProcessKiller;

  // задаем глобальную переменную ServiceInstance

	cProcessKiller::setServiceInstance(killer);

  // запускаем процес

	cProcessKiller::ServiceProcess(argc, argv);

	return 0;

}

Что под капотом (комментарии в коде)

cProcessKiller.h


#ifndef cProcessKiller_H

#define cProcessKiller_H



#include "cWinService.h"

// спецыфические для задачи файлы и константы

#include 

#include 



#define TA_FAILED 0

#define TA_SUCCESS_CLEAN 1

#define TA_SUCCESS_KILL 2

#define TA_SUCCESS_16 3



// путь к папаке логов

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

// системно имя сервиса

#define ZK_SERVICE_NAME L"ZombieKiller";

// имя сервиса для отображения (Win + R -> services.msc)

#define ZK_SERVICE_DISPLAY_NAME L"Zombie killer";



// наслідуємо клас сервіса від cWinService

class cProcessKiller: public cWinService {

public:

	cProcessKiller();

	~cProcessKiller();



protected:

  // переопределяем виртуальные функцыи предка

	bool srvInit();

	bool srvProcess();

	bool srvStop();



	const char* getPathToLog();

	const LPWSTR getServiceNameL();

	const LPWSTR getServiceDNameL();

  

private:

// функции спецыфические для задачи

	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() {



}



// эти функции для обхода ограничения по виртуальности статических функцый

// если у когото есть лучшее решение, буду рад увидеть

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;

}



// в данной задаче ничего не надо иницыализировать

// просто возвращаем успешный результат

bool cProcessKiller::srvInit() {

	return true;

}



// "робоче тело" сервиса

bool cProcessKiller::srvProcess() {

	return stopService();

}



// ответ на запрос ОС об остановке сервиса

// в данном сервисе никаких дополнительных действий ненужно

// поетому просто возвращаем успешный результат

bool cProcessKiller::srvStop() {

	return true;

}



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::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;

Вы можете добавить коментарий на етой странице или на странице форума тут.Постов 7.

Последний комментарий

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]

Имя*E-mail
Код*