一、 编写服务程序
一个服务程序至少包括一个入口函数、服务主函数和控制处理函数。
1. 入口函数
入口函数是可执行程序执行的起点,服务程序的入口函数与一般的可执行程序的入口函数 没有区别。
2. 服务主函数
一个服务程序必须具有服务主函数,服务主函数 是服务启动时执行的入口,也是服务的主线程执行起点。
① 服务主函数 ServiceMain
服务主函数一般称作ServiceMain函数。其函数名称没有任何要求,只是起参数接口和调用类型必须与要求一致。
ServiceMain函数原型如下:
VOID WINAPI ServiceMain(
DWORD dwArgc,
LPTSTR *argv);
服务主函数的参数与 main 函数的参数使用方法类似,但是服务主函数的参数不是通过在命
令行启动时设定的,而是通过 SCM 的相关 API 进行传递的(StartService 函数)。
② 向 SCM 注册服务的主函数 StartServiceCtrIDispatcher
SCM 要对服务进行管理,就必须知道服务程序的服务主函数。服务程序通过调用 StartServiceCtrlDispatcher API函数设置服务主函数,同时通知SCM。
v StartServiceCtrlDispatcher 函数原型如下:
BOOL WINAPI StartServiceCtrlDispatcher(
_In_ CONST SERVICE_TABLE_ENTRYW *lpServiceStartTable
);
结构 SERVICE_TABLE_ENIRY 的原型如下:
typedef struct _SERVICE_TABLE_ENTRYW {
LPWSTR lpServiceName;
LPSERVICE_MAIN_FUNCTIONW lpServiceProc;
}SERVICE_TABLE_ENTRYW, *LPSERVICE_TABLE_ENTRYW;
其中 lpServiceName 为服务名称,lpServiceProc 为指向 ServiceMain 的函数指针。只 要将函数的指针赋值给 lpServiceProc,再调用 StartServiceCtrlDispatcher,这个函数就 成为了服务主函数。
3. 控制处理函数
① 控制处理函数Handle
控制处理函数用于处理SCM向服务传递的服务控制请求。控制处理函数Handler原型如下:
VOID WINAPI ServiceHandler(DWORD opcode);
② 注册控制管理函数
API 函数 RegisterServiceCtrlHandler 用于向 SCM 设置一个服务的控制处理函数。
WINAPI
RegisterServiceCtrlHandlerW(
_In_ LPCWSTR lpServiceName,
_In_ __callback LPHANDLER_FUNCTION lpHandlerProc
);
其中 lpServiceName 为服务名称,lpHandlerProc 为 Handler 函数指针。
二、 实现对服务的控制和管理
使用服 务管理 API 自行编写一个服务管理程序。服务管理程序为系统新建服务,负责启动停止服务 程序,并负责管理服务程序的属性等。
1. 创建、删除服务
① OpenSCManager
WINAPI OpenSCManagerW(
_In_opt_ LPCWSTR lpMachineName,
_In_opt_ LPCWSTR lpDatabaseName,
_In_ DWORD dwDesiredAccess
);
v 参数
lpMachineName:输入参数,机器名,如果是本机则使用NULL。
lpDatabaseName:输入参数,SCM 数据库名,设置为 NULL 或设置为 SERVICES ACTIVE DATABASE,效果等同。
dwDesiredAccess:输入参数,需要的权限,可设置为 SC MANAGER ALL ACCESS、 SC_MANAGER_CREATE_SERVICE、SC_MANAGERCONNECT 等。
v 返回值
SC_HANDLE 类型,SCM 的句柄。
② CreateService
向系统创建服务,创建时指定服务的属性,函数原型如下:
v 参数
CreateService 函数的参数很多,但是设置方法都很简单,直接从参数名就可大体知道参数的意义。
v 返回值
返回 SC_HANDLE 类型,服务的句柄。
③ OpenService
打开服务,获取服务句柄,函数原型如下:
WINAPI OpenServiceW(
_In_ SC_HANDLE hSCManager,
_In_ LPCWSTR lpServiceName,
_In_ DWORD dwDesiredAccess
);
④ DeleteService
删除服务,以服务句柄为参数,函数原型如下:
WINAPI DeleteService(
_In_ SC_HANDLE hService
);
2. 启动、停止服务、向服务发送控制请求
① StartService
启动服务,并设置服务主函数的参数。
<