Windows服务模板

最近写了几个Windows服务,整理了一下服务模板,以备以后使用。
说实话,这些代码是n年前写的了,用了也n久了,但还是发现了一个明显的bug。
其中,有些内容,写的并不好,如静态指针pThis,大家还是尽量不要使用了。

1、服务入口myXXX.cpp

//===================================================
//XXX入口函数

//===================================================
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

#include "XXX.h"

//===================================================
//入口函数
int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int nCmdShow)
{
	UNREFERENCED_PARAMETER(hInstance);
	UNREFERENCED_PARAMETER(hPrevInstance);
	UNREFERENCED_PARAMETER(nCmdShow);

	//获取可执行文件路径
	TCHAR szPath[MAX_PATH];
	TCHAR szLog[MAX_PATH];
	GetModuleFileName(NULL,szPath,MAX_PATH);

	//生成日志目录
	TCHAR *p = _tcsrchr(szPath, '\\');
	if(p!=NULL)*p='\0';
	if (_tcslen(szPath) + _tcslen(TEXT("Log\\")) <= MAX_PATH)
	{
		_stprintf_s(szLog, TEXT("%s\\%s"), szPath, TEXT("Log\\"));
	}
	else
	{
		return -1;
	}

	//判断运行参数
	XXX myService(szLog, true);
	myService.ParseParameters(lpCmdLine);

	return 0;
}

//===================================================

&#91;/code&#93;

2、服务类XXX.h
&#91;code lang="cpp"&#93;
//===================================================
//XXX 服务类封装
#include <windows.h>

//===================================================
//预定义
#define MAX_THREAD_COUNT 64

//===================================================
//XXX CLASS
class XXX
{
private:
	HANDLE	hSemaphore;
	CRITICAL_SECTION cs;

	bool		m_bLog;
	const		TCHAR	*m_szLogPath;
	LPCTSTR		lpServiceName;
	LPCTSTR		lpDisplayName;
	
	SERVICE_STATUS_HANDLE	gSvcStatusHandle;
	SERVICE_STATUS		gSvcStatus;
	HANDLE			ghSvcStopEvent;

	static	XXX	*pThis;
	bool	m_bFinished;

//构造与析构函数
public:
	XXX();
	XXX(const TCHAR *cLogPath,const bool bLog);
	~XXX();

//服务相关函数
private:
	static	void WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv);
	static	void WINAPI SvcCtrlHandler(DWORD dwCtrl);

	void	SvcInitAndRun(DWORD dwArgc,LPTSTR *lpszArgv);
	void	Show_Me_Err();

public:
	int		AddService();
	int		DelService();
	void	LogEvent(LPCTSTR lpMsg);
	void	ParseParameters(LPSTR lpCmdLine);
};

//===================================================

2、服务类XXX.cpp

//===================================================
//XXX服务类的封装实现

//===================================================
//头文件
#include "XXX.h"

//===================================================
//静态成员
XXX *XXX::pThis = NULL;

//===================================================
//构造函数
XXX::XXX(const TCHAR *cLogPath,const bool bLog)
{
	hSemaphore=NULL;

	m_bLog=bLog;
	lpServiceName=TEXT("XXX");
	lpDisplayName=TEXT("XXX");

	ghSvcStopEvent=NULL;
	m_szLogPath=cLogPath;
	m_bFinished = false;

	pThis=this;
}

//===================================================
//析构函数
XXX::~XXX()
{
}

//===================================================
//入口函数
void XXX::ParseParameters(LPSTR lpCmdLine)
{
	//判断运行参数
	//设置SERVICE_TABLE_ENTRY
	SERVICE_TABLE_ENTRY DispatchTable[]=
	{
		{TEXT("XXX"),(LPSERVICE_MAIN_FUNCTION)ServiceMain},
		{NULL,NULL}
	};

	//处理输入参数
	if((0==_stricmp(lpCmdLine,"/i")) || 0==_stricmp(lpCmdLine,"-i"))
	{
		//安装服务"/i -i"
		AddService();
		return;
	}
	else if((0==_stricmp(lpCmdLine,"/u")) || 0==_stricmp(lpCmdLine,"-u"))
	{
		//删除服务"/u -u"
		DelService();
		return;
	}
	else if((0==_stricmp(lpCmdLine,"/h")) || 0==_stricmp(lpCmdLine,"-h"))
	{
		//提示运行参数"/h -h"
		MessageBox(NULL,TEXT(" Install Service  : -i /i\n UnInstall Service: -u /u"),TEXT("XXX"),MB_OK);
		return;
	}
	else
	{
		//设置调试断点
		//DebugBreak();

		//StartServiceCtrlDispatcher运行服务
		if(!StartServiceCtrlDispatcher(DispatchTable))
		{
			LogEvent(TEXT("XXX: Failed To Start!"));
		}
		else
		{
			LogEvent(TEXT("XXX: Started!"));
		}
	}

	return;
}

//===================================================
//添加服务
int XXX::AddService()
{
	//SCMD与Service的句柄
	SC_HANDLE	hSCManager=NULL;
	SC_HANDLE	hService=NULL;

	//连接到SCM,打开SCMD
	hSCManager=OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);
	if(NULL==hSCManager)
	{
		MessageBox(NULL,TEXT("OpenSCManager Failed"),TEXT("XXX"),MB_OK);
		Show_Me_Err();
		return 1;
	}

	//检查服务是否安装
	hService=OpenService(hSCManager,lpServiceName,SERVICE_ALL_ACCESS);
	if(NULL==hService)
	{
		//若服务不存在,创建服务
		TCHAR szFilePath[MAX_PATH];
		GetModuleFileName(GetModuleHandle(NULL),szFilePath,MAX_PATH);

		//自动启动
		hService=CreateService(hSCManager,lpServiceName,lpDisplayName,SERVICE_ALL_ACCESS,
				SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
				SERVICE_AUTO_START,SERVICE_ERROR_NORMAL,szFilePath,NULL,NULL,NULL,NULL,NULL);

		if(NULL==hService)
		{
			MessageBox(NULL,TEXT("CreateService Failed"),TEXT("XXX"),MB_OK);
			Show_Me_Err();
			CloseServiceHandle(hSCManager);
			return 1;
		}
	}
	else
	{
		MessageBox(NULL,TEXT("Service Already Installed!"),TEXT("XXX"),MB_OK);
		CloseServiceHandle(hService);
		CloseServiceHandle(hSCManager);
		return 1;
	}

	//关闭句柄
	CloseServiceHandle(hService);
	CloseServiceHandle(hSCManager);

	LogEvent(TEXT("XXX: AddService Successed!"));
	//ForDebug
	//MessageBox(NULL,TEXT("AddService Successed!"),TEXT("XXX"),MB_OK);
	return 0;
}

//===================================================
//删除服务
int XXX::DelService()
{
	//SCMD与Service的句柄
	SC_HANDLE	hSCManager=NULL;
	SC_HANDLE	hService=NULL;
	SERVICE_STATUS	ServiceStatus;

	//获取SCM句柄,打开SCMD
	hSCManager=OpenSCManager(NULL,NULL,SC_MANAGER_CREATE_SERVICE);
	if(NULL==hSCManager)
	{
		MessageBox(NULL,TEXT("OpenSCManager Failed"),TEXT("XXX"),MB_OK);
		Show_Me_Err();
		return 1;
	}

	//打开服务句柄
	hService=OpenService(hSCManager,lpServiceName,SERVICE_ALL_ACCESS|DELETE);
	if(NULL==hService)
	{
		MessageBox(NULL,TEXT("OpenService Failed"),TEXT("XXX"),MB_OK);
		Show_Me_Err();
		CloseServiceHandle(hSCManager);
		return 1;
	}

	//查询服务状态
	if(0==QueryServiceStatus(hService,&ServiceStatus))
	{
		MessageBox(NULL,TEXT("QueryServiceStatus Failed"),TEXT("XXX"),MB_OK);
		Show_Me_Err();
		CloseServiceHandle(hService);
		CloseServiceHandle(hSCManager);
		return 1;
	}
	else
	{
		//如果服务正在运行,则停止
		if(SERVICE_STOPPED!=ServiceStatus.dwCurrentState)
		{
			if(0==ControlService(hService,SERVICE_CONTROL_STOP,&ServiceStatus))
			{
				MessageBox(NULL,TEXT("ControlService Failed"),TEXT("XXX"),MB_OK);
				Show_Me_Err();
				CloseServiceHandle(hService);
				CloseServiceHandle(hSCManager);
				return 1;
			}
		}

		//删除服务
		if(0==DeleteService(hService))
		{
			MessageBox(NULL,TEXT("DeleteService Fialed!"),TEXT("XXX"),MB_OK);
			Show_Me_Err();
			CloseServiceHandle(hService);
			CloseServiceHandle(hSCManager);
			return 1;
		}
	}

	CloseServiceHandle(hService);
	CloseServiceHandle(hSCManager);

	LogEvent(TEXT("XXX: DelService Successed!"));
	//ForDebug
	//MessageBox(NULL,TEXT("DelService Successed!"),TEXT("XXX"),MB_OK);
	return 0;
}

//===================================================
//服务入口函数
void WINAPI XXX::ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv)
{
	//注册服务控制程序
	pThis->gSvcStatusHandle=RegisterServiceCtrlHandler(pThis->lpServiceName,SvcCtrlHandler);
	if(0==pThis->gSvcStatusHandle)
	{
		//注册失败,返回
		pThis->LogEvent(TEXT("XXX: RegisterServiceCtrlHandler Failed"));
		return;
	}

	//设置服务状态SERVICE_START_PENDING
	pThis->gSvcStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
	pThis->gSvcStatus.dwCurrentState=SERVICE_START_PENDING;
	pThis->gSvcStatus.dwControlsAccepted=0;
	pThis->gSvcStatus.dwWin32ExitCode=NO_ERROR;
	pThis->gSvcStatus.dwServiceSpecificExitCode=0;
	pThis->gSvcStatus.dwCheckPoint=0;
	pThis->gSvcStatus.dwWaitHint=10000;
	SetServiceStatus(pThis->gSvcStatusHandle,&(pThis->gSvcStatus));

	//运行服务函数
	pThis->SvcInitAndRun(dwArgc, lpszArgv);

	//停止服务
	pThis->gSvcStatus.dwCurrentState=SERVICE_STOPPED;
	pThis->gSvcStatus.dwWaitHint=0;
	pThis->gSvcStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;
	pThis->gSvcStatus.dwCheckPoint=0;
	SetServiceStatus(pThis->gSvcStatusHandle,&(pThis->gSvcStatus));
}

//===================================================
//服务函数
void XXX::SvcInitAndRun(DWORD dwArgc,LPTSTR *lpszArgv)
{
	UNREFERENCED_PARAMETER(dwArgc);
	UNREFERENCED_PARAMETER(lpszArgv);

	//创建事件
	ghSvcStopEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
	if(ghSvcStopEvent==NULL)
	{
		//创建事件失败,停止服务,返回
		gSvcStatus.dwCurrentState=SERVICE_STOPPED;
		gSvcStatus.dwWaitHint=0;
		gSvcStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;
		gSvcStatus.dwCheckPoint=0;
		SetServiceStatus(gSvcStatusHandle,&gSvcStatus);
		return;
	}

	//设置服务状态SERVICE_RUNNING
	gSvcStatus.dwCurrentState=SERVICE_RUNNING;
	gSvcStatus.dwWaitHint=0;
	gSvcStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;
	gSvcStatus.dwCheckPoint=0;
	SetServiceStatus(gSvcStatusHandle,&gSvcStatus);

	//设置断点
	while (!IsDebuggerPresent()) 
	{ 
		Sleep(100); 
	} 
	DebugBreak();

	//创建信号量
	hSemaphore=CreateSemaphore(NULL,MAX_THREAD_COUNT,MAX_THREAD_COUNT,TEXT("NAS_TEST_SEMAPHORE"));
	if(NULL==hSemaphore)  
	{
		return;
	}

	//初始化关键区
	InitializeCriticalSection(&cs);

	//处理请求
	while(!m_bFinished)
	{
		//进入关键区
		EnterCriticalSection(&cs);
		while (!m_bFinished)
		{
			if(WAIT_TIMEOUT==WaitForSingleObject(ghSvcStopEvent,100))
			{
				//这里处理你的线程逻辑
				//每个线程启动的时候WaitForSingleObject占用一个信号量
				//线程退出时ReleaseSemaphore释放信号量

			}
			else
			{
				LogEvent(TEXT("XXX is gonging down."));
				m_bFinished = true;
			}
		}
		//退出关键区
		LeaveCriticalSection(&cs);

		if (!m_bFinished)
		{
			//等待线程0.2秒
			Sleep(200);
		}
	}

	//等待所有线程结束
	WaitForMultipleObjects(MAX_THREAD_COUNT, &hSemaphore, true, 10000L);
	//WaitForMultipleObjects(1,&hSemaphore,true,INFINITE);

	//释放信号量
	CloseHandle(hSemaphore);
	
	//释放关键区
	DeleteCriticalSection(&cs);

	return;
}

//===================================================
//服务控制函数
void WINAPI XXX::SvcCtrlHandler(DWORD dwCtrl)
{
	switch(dwCtrl)
	{
		case SERVICE_CONTROL_STOP:
			//设置服务状态SERVICE_ACCEPT_STOP
			pThis->gSvcStatus.dwCurrentState=SERVICE_STOP_PENDING;
			pThis->gSvcStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP;
			pThis->gSvcStatus.dwCheckPoint=0;
			pThis->gSvcStatus.dwWaitHint=10000;
			SetServiceStatus(pThis->gSvcStatusHandle,&(pThis->gSvcStatus));
			//触发事件
			SetEvent(pThis->ghSvcStopEvent);
			break;
		case SERVICE_CONTROL_PAUSE:
			break;
		case SERVICE_CONTROL_CONTINUE:
			break;
		case SERVICE_CONTROL_INTERROGATE:
			break;
		case SERVICE_CONTROL_SHUTDOWN:
			break;
		default:
			pThis->LogEvent(TEXT("XXX: Bad Service Request!"));
	}
}

//===================================================
//在事件查看器中记录消息
void XXX::LogEvent(LPCTSTR lpMsg)
{
	HANDLE	hEventSource;
	LPCTSTR	lpszStrings[1];

	lpszStrings[0]=lpMsg;

	//在“事件查看器->应用程序->信息”中进行记录
	hEventSource=RegisterEventSource(NULL,lpServiceName);
	if(NULL!=hEventSource)
	{
		ReportEvent(hEventSource,EVENTLOG_INFORMATION_TYPE,0,0,NULL,1,0,lpszStrings,NULL);
		DeregisterEventSource(hEventSource);
	}
}

//===================================================
//输出GetLastErr()信息
void XXX::Show_Me_Err()
{
	if(!m_bLog)return;

	DWORD	dwErrNo;
	LPTSTR	lpBuffer;
	dwErrNo=GetLastError();
	FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_FROM_SYSTEM,
		NULL,dwErrNo,LANG_NEUTRAL,(LPTSTR)&lpBuffer,0,NULL);
	MessageBox(NULL,lpBuffer,TEXT("XXX GetLastError"),MB_OK);
	LocalFree(lpBuffer);
}

//===================================================

Comments are closed.