定义全局变量
#define SVCNAME TEXT("SvcName")
SERVICE_STATUS gSvcStatus;
SERVICE_STATUS_HANDLE gSvcStatusHandle;
HANDLE ghSvcStopEvent = NULL;
VOID WINAPI SvcMain( DWORD dwArgc, LPTSTR *lpszArgv ) { // 注册服务控制回调函数 gSvcStatusHandle = RegisterServiceCtrlHandler( SVCNAME, SvcCtrlHandler); if( !gSvcStatusHandle ) { SvcReportEvent(TEXT("RegisterServiceCtrlHandler")); return; } // 设置服务类型 gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; gSvcStatus.dwServiceSpecificExitCode = 0; // 向SCM汇报服务状态,正在初始化 ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 3000 ); // 执行服务相关的初始化工作 SvcInit( dwArgc, lpszArgv ); }
初始化
VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv) { // 创建一个手动事件,当收到信号时,服务退出。 ghSvcStopEvent = CreateEvent( NULL, // default security attributes TRUE, // manual reset event FALSE, // not signaled NULL); // no name if ( ghSvcStopEvent == NULL) { ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 ); return; } // 初始化完成后,汇报状态。 ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 ); // 执行服务的所有逻辑,直到收到服务停止的信号。 while(1) { WaitForSingleObject(ghSvcStopEvent, INFINITE);
//汇报服务停止的状态。 ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 ); return; } }
VOID ReportSvcStatus( DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) { 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++; // 将服务的状态汇报给SCM SetServiceStatus( gSvcStatusHandle, &gSvcStatus ); }
服务控制程序
VOID WINAPI SvcCtrlHandler( DWORD dwCtrl ) { // 处理服务控制的请求 switch(dwCtrl) { case SERVICE_CONTROL_STOP: ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); // 请求停止服务 SetEvent(ghSvcStopEvent); ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0); return; case SERVICE_CONTROL_INTERROGATE: break; default: break; } }