最近写了几个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; } //=================================================== [/code] 2、服务类XXX.h [code lang="cpp"] //=================================================== //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); } //===================================================