windows系统服务入口的封装类,service是基类,service_manager是管理类。支持UNICODE,可以多服务封装在一个程序里面,过程当然都是自动的。拥有自动防错系统,在服务异常退出的时候会去关闭服务,而不是开着服务直接没了进程。写一个类,继承service,然后在哪里出一个实例,就可以了。service中有很多虚函数,可以重载了监听对应事件(我应该写的比较明白吧)。get_service_name,返回UNICODE的字符串指针,定义服务名称。注意是纯虚函数,必须实现。get_dependence,也是返回UNICODE的字符指针。指明这个服务依赖什么服务。get_service_type返回服务类型,其实也就是是否可以交互。get_contral_accepts,支持的信号(例如是否可以暂停),默认可以暂停。on_start开始时候调用的函数,下同。

使用方法

#include
#include "service.h"

class test_service : public service{
public:
	virtual LPTSTRget_service_name ();
	virtual DWORD on_start (DWORD argc, LPTSTR * argv);
	virtual DWORD on_stop ();
	virtual DWORD on_shutdown ();
};

LPTSTR test_service::get_service_name ()
{
	return _T ("test_service");
}

DWORD test_service::on_start (DWORD argc, LPTSTR * argv)
{
	return service::on_start (argc, argv);
}

DWORD test_service::on_stop ()
{
	return service::on_stop ();
}

DWORD test_service::on_shutdown ()
{
	return service::on_shutdown ();
}

int _tmain (int argc, _TCHAR * argv[])
{
	test_service ts;
	if (argc == 1)
		service_manager::start ();
	else if (!_tcscmp (argv[1], _T ("install")))
		service_manager::install_services (NULL, false);
	else if (!_tcscmp (argv[1], _T ("remove")))
		service_manager::remove_services (NULL);
	return 0;
}

------------service.h-------------------
#include
using namespace std;
#include
#pragma comment(lib, "psapi")

typedef basic_string < TCHAR > tstring;

#ifndef _SERVICE_H_
#define _SERVICE_H_

class service {
public:
	service ();
	~service ();
	virtual LPTSTRget_service_name () = 0;
	virtual LPTSTRget_dependence ();
	virtual DWORD get_service_type ();
	virtual DWORD get_contral_accepts ();
	virtual DWORD on_start (DWORD argc, LPTSTR * argv);
	virtual DWORD on_stop ();
	virtual DWORD on_interrogate ();
	virtual DWORD on_pause ();
	virtual DWORD on_continue ();
	virtual DWORD on_shutdown ();
	voidpre_start (SERVICE_STATUS_HANDLE hServiceStatus,
			   DWORD argc, LPTSTR * argv);
	BOOL SetServiceStatus (DWORD dwState);
protected:
	SERVICE_STATUS_HANDLE hServiceStatus;
	SERVICE_STATUS ServiceStatus;
};

class service_manager {
public:
	service_manager ();
	~service_manager ();
	DWORDregister_service (service * s);
	DWORDunregister_service (service * s);
	LPSERVICE_TABLE_ENTRYget_service_entries ();
	service *get_service (LPCTSTR lpName);
	static service_manager *get_service_manager();
	static intinstall_services (LPCTSTR lpServiceName, bool
					autostart);
	static intremove_services (LPCTSTR lpServiceName);
	static intstart();
	static void WINAPIservice_start (DWORD argc, LPTSTR * argv);
	static DWORD WINAPIctrl_handler (DWORD dwControl, DWORD
					 dwEventType,
					 LPVOID lpEventData, LPVOID lpContext);
	static TCHAR *service_status_name[];
protected:
	static service_manager *this_for_static;
	vector < service * >service_list;
};

#endif //_SERVICE_H_

----------------------------------------

------------service.cpp-----------------

// service.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"

#define PRINTERROR(x) _tprintf (_T ("%s failed, errorcode 0x%0.8X\n"),(x), GetLastError ())

service_manager *service_manager::this_for_static = NULL;
TCHAR *service_manager::service_status_name[] = {
	_T ("SERVICE_UNKNOWN"),
	_T ("SERVICE_STOPPED"),
	_T ("SERVICE_START_PENDING"),
	_T ("SERVICE_STOP_PENDING"),
	_T ("SERVICE_RUNNING"),
	_T ("SERVICE_CONTINUE_PENDING"),
	_T ("SERVICE_PAUSE_PENDING"),
	_T ("SERVICE_PAUSED")
};

service::service ()
{
	if (service_manager::get_service_manager () == NULL)
		new service_manager ();
	service_manager::get_service_manager ()->register_service
		(this);
}

service::~service ()
{
	if (service_manager::get_service_manager () == NULL)
		return;
	service_manager::get_service_manager ()->unregister_service(this);
}

LPTSTR service::get_dependence ()
{
	return NULL;
}

DWORD service::get_service_type ()
{
	return 0;
}

DWORD service::get_contral_accepts ()
{
	return SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN |
		SERVICE_ACCEPT_STOP;
}

DWORD service::on_start (DWORD argc, LPTSTR * argv)
{
	return SERVICE_RUNNING;
}

DWORD service::on_stop ()
{
	return SERVICE_STOPPED;
}

DWORD service::on_interrogate ()
{
	return SERVICE_RUNNING;
}

DWORD service::on_pause ()
{
	return SERVICE_PAUSED;
}

DWORD service::on_continue ()
{
	return SERVICE_RUNNING;
}

DWORD service::on_shutdown ()
{
	return SERVICE_STOPPED;
}

void service::pre_start (SERVICE_STATUS_HANDLE hServiceStatus,
			 DWORD argc, LPTSTR * argv)
{
	this->hServiceStatus = hServiceStatus;
	ServiceStatus.dwServiceType = SERVICE_WIN32;
	ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
	ServiceStatus.dwControlsAccepted = 0;
	ServiceStatus.dwWin32ExitCode = 0;
	ServiceStatus.dwServiceSpecificExitCode = 0;
	ServiceStatus.dwCheckPoint = 0;
	ServiceStatus.dwWaitHint = 10000;
	SetServiceStatus (0);
	ServiceStatus.dwCurrentState = on_start (argc, argv);
	if (ServiceStatus.dwCurrentState == SERVICE_STOPPED)
		ServiceStatus.dwWin32ExitCode = ServiceStatus.dwCurrentState;
	ServiceStatus.dwCheckPoint = 0;
	ServiceStatus.dwWaitHint = 0;
	ServiceStatus.dwControlsAccepted = get_contral_accepts ();
	SetServiceStatus (0);
	return;
}

BOOL service::SetServiceStatus (DWORD dwState)
{
	TCHAR lpOutString[0x400];
	if (dwState != 0)
		ServiceStatus.dwCurrentState = dwState;
	if (ServiceStatus.dwCurrentState > 7)
		return 0;
	BOOL rslt =::SetServiceStatus (hServiceStatus, &ServiceStatus);
	if (rslt)
		_stprintf (lpOutString,
			   _T ("%s set service status %s successed.\n"),
			   get_service_name (),
			   service_manager::service_status_name[ServiceStatus.
								dwCurrentState]);
	else
		_stprintf (lpOutString,
			   _T
			   ("%s set service status %s failed, errorcode 0x%0.8X\n"),
			   get_service_name (),
			   service_manager::service_status_name[ServiceStatus.
								dwCurrentState],
			   GetLastError ());
	OutputDebugString ((LPCTSTR) lpOutString);
	return rslt;
}

service_manager::service_manager ()
{
	if (this_for_static != NULL)
		return;
	this_for_static = this;
}

service_manager::\~service_manager ()
{
	this_for_static = NULL;
}

DWORD service_manager::register_service (service * s)
{
	vector < service * >::iterator iter;
	iter = service_list.begin ();
	for (; iter != service_list.end (); iter++)
		if (*iter == s)
			return 1;
	service_list.push_back (s);
	return 0;
}

DWORD service_manager::unregister_service (service * s)
{
	vector < service * >::iterator iter;
	iter = service_list.begin ();
	for (; iter != service_list.end (); iter++)
		if (*iter == s) {
			service_list.erase (iter);
			return 0;
		}
	return -1;
}

LPSERVICE_TABLE_ENTRY service_manager::get_service_entries ()
{
	UINT i;
	LPSERVICE_TABLE_ENTRY lte = NULL;
	lte = new SERVICE_TABLE_ENTRY[service_list.size () + 1];
	for (i = 0; i < service_list.size (); i++) {
		lte[i].lpServiceName = service_list[i]->get_service_name
			();
		lte[i].lpServiceProc = (LPSERVICE_MAIN_FUNCTION) service_start;
	}
	lte[i].lpServiceName = NULL;
	lte[i].lpServiceProc = NULL;
	return lte;
}

service *service_manager::get_service (LPCTSTR lpName)
{
	for (UINT i = 0; i < service_list.size (); i++)
		if (!_tcscmp (service_list[i]->get_service_name (), lpName))
			return service_list[i];
	return NULL;
}

int service_manager::install_services (LPCTSTR lpServiceName, bool
					   autostart)
{
	UINT i;
	int rslt = 0;
	DWORD service_type;
	TCHAR binary_path[0x400];
	SC_HANDLE hSCManager = NULL, hService = NULL;
	service *pservice;
	if (lpServiceName == NULL) {
		for (i = 0; i < this_for_static->service_list.size (); i++)
			install_services (this_for_static->service_list[i]->
					  get_service_name (), autostart);
		return 0;
	}
	pservice = this_for_static->get_service (lpServiceName);
	if (pservice == NULL) {
		_tprintf (_T ("get_service %s failed, don't have this service\n"),
			  lpServiceName);
		return -1;
	}
	if (!GetModuleFileNameEx (GetCurrentProcess (), NULL, binary_path,
				  0x400)) {
		PRINTERROR (_T ("GetModuleFileNameEx"));
		return -1;
	}
	if (this_for_static->service_list.size () < 2)
		service_type = SERVICE_WIN32_OWN_PROCESS;
	else
		service_type = SERVICE_WIN32_SHARE_PROCESS;
	__try {
		hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
		if (hSCManager == NULL) {
			rslt = -1;
			__leave;
		}
		hService = CreateService (hSCManager, lpServiceName, lpServiceName,
					  SC_MANAGER_ALL_ACCESS,
					  pservice->
					  get_service_type () | service_type,
					  (autostart ? SERVICE_AUTO_START :
					   SERVICE_DEMAND_START),
					  SERVICE_ERROR_NORMAL, binary_path, NULL,
					  NULL, pservice->get_dependence (), NULL,
					  NULL);
		if (hService == NULL) {
			rslt = -2;
			__leave;
		}
	}
	__finally {
		if (hService != NULL)
			CloseServiceHandle (hService);
		if (hSCManager != NULL)
			CloseServiceHandle (hSCManager);
		if (rslt == 0)
			_tprintf (_T ("install_services %s successed\n"), lpServiceName);
		if (rslt == -1)
			PRINTERROR (_T ("OpenSCManager"));
		if (rslt == -2)
			PRINTERROR (_T ("CreateService"));
	}
	return rslt;
}

int service_manager::remove_services (LPCTSTR lpServiceName)
{
	int rslt = 0;
	UINT i;
	SC_HANDLE hSCManager, hService;
	service *pservice;
	if (lpServiceName == NULL) {
		for (i = 0; i < this_for_static->service_list.size (); i++)
			remove_services (this_for_static->service_list[i]->
					 get_service_name ());
		return 0;
	}
	pservice = this_for_static->get_service (lpServiceName);
	if (pservice == NULL) {
		_tprintf (_T ("get_service failed, don't have this service\n"));
		return -1;
	}
	__try {
		hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
		if (hSCManager == NULL) {
			rslt = -1;
			__leave;
		}
		hService =
			OpenService (hSCManager, lpServiceName, SC_MANAGER_ALL_ACCESS);
		if (hService == NULL) {
			rslt = -2;
			__leave;
		}
		if (!DeleteService (hService)) {
			rslt = -3;
			__leave;
		}
	}
	__finally {
		if (hService != NULL)
			CloseServiceHandle (hService);
		if (hSCManager != NULL)
			CloseServiceHandle (hSCManager);
		if (rslt == 0)
			_tprintf (_T ("remove_services %s successed\n"), lpServiceName);
		if (rslt == -1)
			PRINTERROR (_T ("OpenSCManager"));
		if (rslt == -2)
			PRINTERROR (_T ("OpenService"));
		if (rslt == -3)
			PRINTERROR (_T ("DeleteService"));
	}
	return rslt;
}

int service_manager::start ()
{
	if (!StartServiceCtrlDispatcher
		(this_for_static->get_service_entries ()))
		OutputDebugString (_T ("StartServiceCtrlDispatcher failed\n"));
	return 0;
}

void WINAPI service_manager::service_start (DWORD argc, LPTSTR *
						argv)
{
	SERVICE_STATUS_HANDLE hServiceStatus;
	service *pservice = this_for_static->get_service
		(argv[0]);
	if (pservice == NULL) {
		OutputDebugString (_T
				   ("get_service failed, don't have this service\n"));
		return;
	}
	hServiceStatus =
		RegisterServiceCtrlHandlerEx (argv[0], ctrl_handler, (LPVOID)
						  pservice);
	if (hServiceStatus == NULL) {
		OutputDebugString (_T ("RegisterServiceCtrlHandlerEx return NULL\n"));
		return;
	}
	__try {
		pservice->pre_start (hServiceStatus, argc, argv);
	}
	__except (EXCEPTION_EXECUTE_HANDLER) {
		pservice->SetServiceStatus (SERVICE_STOPPED);
	}
	return;
}

DWORD WINAPI service_manager::ctrl_handler (DWORD dwControl,
						DWORD dwEventType,
						LPVOID lpEventData,
						LPVOID lpContext)
{
	DWORD status;
	service *pservice = (service *) lpContext;
	SetLastError (NO_ERROR);
	__try {
		switch (dwControl) {
		case SERVICE_CONTROL_STOP:
			status = pservice->on_stop ();
			break;
		case SERVICE_CONTROL_SHUTDOWN:
			status = pservice->on_shutdown ();
			break;
		case SERVICE_CONTROL_PAUSE:
			status = pservice->on_pause ();
			break;
		case SERVICE_CONTROL_INTERROGATE:
			status = pservice->on_interrogate ();
			break;
		case SERVICE_CONTROL_CONTINUE:
			status = pservice->on_continue ();
			break;
		default:
			return GetLastError ();
		}
		pservice->SetServiceStatus (status);
	}
	__except (EXCEPTION_EXECUTE_HANDLER) {
		pservice->SetServiceStatus (SERVICE_STOPPED);
	}
	return GetLastError ();
}

service_manager *service_manager::get_service_manager ()
{
	return this_for_static;
}

----------------------------------------

之所有list没有写成map是因为在某个服务处理过程中可能需要用到服务的名称。写成map就需要反向查询,也不是很方便。register_service中会查询这个服务是否已经注册过,注意不能用服务名对比的方法。这也是我才发现的一个问题,C++在基类的构造函数中的时候,虚函数指针是指向基类虚函数表的。在某个service子类构造的时候,其基类(service)构造函数会自动调用register_service方法注册自身。如果在register_service用取得服务名的方法,此时虚函数指针指向了基类的虚函数表。也就是说,我们会调用到一个纯虚函数入口,从而产生C++错误。所以必须手工来匹配指针,大家忍耐忍耐。