最近写了几个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);
}
//===================================================