摘要: 何为服务?Windows 会话中可长时间运行的可执行应用程序。这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面。这种服务非常适合在服务器上使用,或任何时候,为了不影响在同一台计算机上工作的其他用户,需要长时间运行功能时使用。一个服务首先是一个Win32可执行程序,如果要写一个功能完备且强大的服务,需要熟悉动态连接库(DLL)、结构异常处理、内存映射文件、虚拟内存、设备I/O、线程及其同步、Unicode以及其他的由WinAPI函数提供的应用接口。
Windows Service概要
实现一个服务程序,主要需要完成两个部分:
- 服务运行函数(相当于
Thread
中的run
):服务运行函数,一般被呼为ServiceMain
。但是它的名称与ThreadProc
一样,其命名没有特殊要求,只是参数接口和调用类型必须与要求一致:
void WINAPI serviceImpl(DWORD argc, LPCWSTR* argv);
- 服务控制函数:Windows中提供了强大的命令行工具
sc.exe
,用于对服务进行管理。可以实现对服务的所有控制,包括安装、删除、配置、启动、停止等。为此,我们需要在自己的服务程序中对这些命令做出响应。也就是需要实现一个服务控制函数,当接收到不同命令的时候,执行不同的操作,具体操作自行定义。
一个服务包括若干属性,包括服务名称、显示名称、服务类型、描述、可执行文件路径、启动类型、服务状态、启动参数、依存关系等。
- 服务名称:唯一标识一个服务;
- 显示名称:在系统服务管理界面和sc.exe中显示名称;
- 服务类型:包括SERVICE_FILE_SYSTEM_DRIVER(文件系统驱动服务)、SERVICE_KERNEL_DRIVER(驱动服务)——(2种)运行于内核态。
SERVICE_WIN32_OWN_PROCESS(独立进程服务)、SERVICE_WIN32_SHARE_PROCESS(共享进程服务)——(2种)运行于用户态。
本文主要讲解Windows服务运行函数开发。Windows服务与多线程极为类似,服务运行函数一般称为ServiceMain
,与线程中的ThreadProc
(线程执行体)一样,其函数名并没有特殊的要求,只要求其参数接口和返回值调用类型与要求一致即可,这里所说的ServiceMain(服务运行函数)也可以理解为Thread中的run
,虽然不是很恰当。服务程序通过调用StartServiceCtrlDispatcher
API函数设置服务主函数。
其中,StartServiceCtrlDispatcher 函数原型如下:
StartServiceCtrlDispatcherW(
_In_ CONST SERVICE_TABLE_ENTRYW *lpServiceStartTable
);
以上函数中只有一个结构体,SERVICE_TABLE_ENTRYW
的原型也给出如下: