编程实现
一个完整的服务分为安装服务程序,主体服务程序和卸载服务程序。我们先来写服务的主体部分,示例代码如下:
void main()
{
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{"scuhkr", BDServiceMain},
{NULL, NULL} //"哨兵"
};
//连接到服务控制管理器
StartServiceCtrlDispatcher(ServiceTable);
}
路人甲:什么,就这么短?你想侮辱广大鸟儿的智慧?呵呵,先别急,听我慢慢道来:上面代码中,我们先给出了一个SERVICE_TABLE_ENTRY结构数组,每个成员描述了调用进程提供的服务,这里我们只安装了一个服务名为Scuhkr的服务,后面的BDServiceMain()我们称之为服务主函数,通过回调该函数提供了服务入口地址,它原形的参数必须定义成如下形式:
VOID WINAPI BDServiceMain(
DWORD dwArgc, //lpszArgv参数个数
LPTSTR* lpszArgv //该数组第一个的参数指定了服务名,可以在后面被
StartService()来调用
);
SERVICE_TABLE_ENTRY结构数组要求最后一个成员组都为NULL,我们称之为“哨兵”(所有值都为NULL),表示该服务表末尾。一个服务启动后,马上调用StartServiceCtrlDispatcher()通知服务控制程序服务正在执行,并提供服务函数的地址。StartServiceCtrlDispatcher()只需要一个至少有两SERVICE_TABLE_ENTRY结构的数组,它为每个服务启动一个线程,一直等到它们结束才返回。
本程序只提供了一个服务函数BDServiceMain(),下面我们来下完成这个函数的功能,示例代码如下:
void WINAPI BDServiceMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
DWORD dwThreadId; //存放线程ID
//通过RegisterServiceCtrlHandler()与服务控制程序建立一个通信的协议。
//BDHandler()是我们的服务控制程序,它被可以被用来开始,暂停,恢复,停止服务等控制操作
if (!(ServiceStatusHandle = RegisterServiceCtrlHandler("scuhkr",
BDHandler)))
return;
//表示该服务私有
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
//初始化服务,正在开始
ServiceStatus.dwCurrentState = SERVICE_START_PENDING; //
//服务可以接受的请求,这里我们只接受停止服务请求和暂停恢复请求
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_PAUSE_CONTINUE;
//下面几个一般我们不大关心,全为0
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCheckPoint