2.服务入口点函数
服务入口点函数 service_main 首先调用系统函数 RegisterServiceCtrlHandler 注册服务控制处理函数 service_ctrl,然后调用 ReportStatusToSCMgr 函数,它通过系统函数 SetServiceStatus 更新服务的状态,然后调用特定的服务初始化入口函数 ServiceStart 完成具体的初始化工作。
//服务入口点函数
void ServiceStart(DWORD dwArgc,LPTSTR* lpszArgv);//具体服务的初始化入口函数
void WINAPI Service_Main(DWORD dwArgc, LPTSTR *lpszArgv)
{
//注册服务控制处理函数
sshStatusHandle=RegisterServiceCtrlHandler(TEXT(SZSERVICENAME),Service_Ctrl);
//如果注册失败
if(!sshStatusHandle)
{
goto cleanup;
return;
}
//初始化 SERVICE_STATUS 结构中的成员
ssStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
ssStatus.dwServiceSpecificExitCode=0;
//更新服务状态
if(!ReportStatusToSCMgr(
SERVICE_START_PENDING,//服务状态,The service is starting.
NO_ERROR, //退出码
3000)) //等待时间
goto cleanup; //更新服务状态失败则转向 cleanup
ServiceStart(dwArgc,lpszArgv);
return;
cleanup:
//把服务状态更新为 SERVICE_STOPPED,并退出。
if(sshStatusHandle)
(void)ReportStatusToSCMgr(SERVICE_STOPPED,dwErr,0);
}
3.控制处理程序函数
3.控制处理程序函数
函数 Service_Ctrl 是服务的控制处理程序函数,由主函数线程的控制分发程序引用。在处理控制请求码时,应该在确定的时间间隔内更新服务状态检查点,避免发生服务不能响应的错误。
//控制处理程序函数
void WINAPI Service_Ctrl(DWORD dwCtrlCode)
{
//处理控制请求码
switch(dwCtrlCode)
{
//先更新服务状态为 SERVICDE_STOP_PENDING,再停止服务。
case SERVICE_CONTROL_STOP:
ReportStatusToSCMgr(SERVICE_STOP_PENDING,NO_ERROR,500);
ServiceStop(); //由具体的服务程序实现
return;
//暂停服务
case SERVICE_CONTROL_PAUSE:
ReportStatusToSCMgr(SERVICE_STOP_PENDING,NO_ERROR,500);
ServicePause(); //由具体的服务程序实现
ssStatus.dwCurrentState=SERVICE_PAUSED;
return;
//继续服务
case SERVICE_CONTROL_CONTINUE:
ReportStatusToSCMgr(SERVICE_STOP_PENDING,NO_ERROR,500);
ServiceContinue(); //由具体的服务程序实现
ssStatus.dwCurrentState=SERVICE_RUNNING;
return;
//更新服务状态
case SERVICE_CONTROL_INTERROGATE:
break;
//无效控制码
default:
break;
}
ReportStatusToSCMgr(ssStatus.dwCurrentState,NO_ERROR,0);
}
除了系统定义的五种控制码外(还有一种是:SERVICE_CONTROL_SHUTDOWN),用户还可自定义控制码,其取值范围是128-255。用户可以通过控制面板中的服务项向特定服务程序的控制处理函数发送控制码,程序员可以调用系统函数 ControlService 直接向服务程序的控制处理函数发送控制码。其函数原型如下:
BOOL ControlService(
SC_HANDLE hService,
DWORD dwControl,
LPSERVICE_STATUS lpServiceStatus
);
hService :函数 OpenService or CreateService 返回的服务程序句柄。
dwControl :控制码,不能是SERVICE_CONTROL_SHUTDOWN。
lpServiceStatus:返回最后收到的服务状态信息。