操作 NT 服务
操作 NT 服务OpenSCManager 打开目标计算机上的“服务控制管理器”SCM返回指向该管理器的指针。OpenService 打开服务返回指向该服务的指针。StartService 传递一个字符串数组并将其作为参数启动一个现有的服务。ControlService 控制一个已经打开的服务。CreateService 创建一个新服务DeleteService 删除一个已有的服务StartServiceCtrlDispatcher 启动服务ChangeServiceConfigWindows服务是其实一种特殊的二进制可执行文件后缀名一般为EXE之所以说它特殊因为它具有同Windows
NT/2K系统的服务控制管理器(SCM: Service Control Manager)通信。 服务控制管理器通过维护数据库对已经安装到系统的所有服务和驱动程序进行统一而安全的控制和管理。服务
控制管理器是一个远程进程调用(RPC)服务器在系统导入时自动启动。 一个简单的服务程序至少包括一些几个部分 1. Win32/控制台应用主程序 2. 一个服务主程序作为服务的导入点 3. 一个服务控制处理器就是同服务控制管理器SCM通信的函数 4. 一个服务安装/反安装程序用于将一个EXE文件注册为一个服务。 下面我们针对上述几个部分分别介绍怎样构造一个Windows服务。
控制台应用主程序
在Win32下为WinMain函数在控制台下为main函数是服务的主程序。下面是服务主程序中至少要包含的语句。
#include "Winsvc.h" //服务头文件
main(){ ...... SERVICE_TABLE_ENTRY Table[],}; StartServiceCtrlDispatcher(Table); ......}
当然这是一个非常简单的主程序了。这里main只做了一件事情就是填写SERVICE_TABLE_ENTRY结构数组Table。
Table[0][0]是服务的名字(可以是您喜欢的任意字符串,此处我用的是gkeyService)Table[0][1]指定了服务主程
序的名字实际上这是一个指向服务主程序的函数指针它也可以用您喜欢的函数名字(我用的是gkeyServiceMain)
。现在通过调用参数为SERVICE_TABLE_ENTRY结构数组的函数StartServiceCtrlDispatcher()开始启动服务解析。注
意这个函数的参数必须要符合一定的格式Table[1][0]和Table[1][1]必须是NULL就是说到了数组的结尾。当然
并非必须这样如果需要在这个执行程序中运行多个服务可以在这个数组列表中加入更多的入口构成多对服务
名称和服务中程序自然您需要在以下的步骤中需要为每个服务构造相应的完成函数。
服务主程序
典型的服务主程序的声明如下
void WINAPI gkeyServiceMain( DWORD argc, LPTSTR *argv )
在gkeyServiceMain函数中需要实现的主要步骤包括 1. 用合适的值填写SERVICE_STATUS结构来完成同服务控制管理器SCM的通信2. 在列表中注册前面所说的服务控制处理函数3. 调用实际的处理函数。
为了完成上述功能需要使用两个全局变量SERVICE_STATUS m_ServiceStatus;SERVICE_STATUS_HANDLE m_ServiceStatusHandle;
服务主程序gkeyServiceMain()能够象通常的c/c里的main()函数一样接受命令行参数并且接受参数的方式
也完全一样。第一个参数argc包含了传递给服务的参数个数同c/c的main()一样至少有一个参数就是服务应用本
身。第二个参数是一个字符指针数组的指针。同main()函数一样数组的第一个值总是指向服务的名字。 使用SERVICE_STATUS数据结构记录服务的当前状态并将状态及时通告给服务控制管理器SCM使用一个API函
数SetServiceStatus()来实现这一目标。SERVICE_STATUS的数据成结构员如下:
dwServiceType SERVICE_WIN32; dwCurrentState SERVICE_START_PENDING; //试图启动(初始状态)dwControlsAccepted SERVICE_ACCEPT_STOP; //仅接收服务控制程序的启动/停止,服务控制程序通常在
Windows NT下的控制面板或者Windows 2K下的管理工具我们也可以设置服务接受暂停/继续功能。
在服务主程序gkeyServiceMain()的开始应该设置SERVICE_STATUS的状态字段dwCurrentState为
SERVICE_START_PENDING通知SCM服务处于运行状态。如果发生错误应该发送SERVICE_STOPPED通知服务控制管理
器SCM。缺省状态下服务控制管理器SCM将监视服务的活动如果2分钟之类没有发现进程活动就杀死这个服务。
使用API函数RegisterServiceCtrlHandler()设置服务控制管理器SCM的服务控制处理函数这个函数需要两个
参数一个是服务名称字符串一个是服务控制处理函数句柄。
现在要设置dwCurrentState为SERVICE_RUNNING用以通知服务已经启动。
服务控制处理函数
服务控制管理器SCM使用服务控制处理函数和服务程序进行通信来了解服务的诸如启动、停止、暂停或继续等用
户指令它主要包含一个switch语句来处理每种情况调用相应的步骤来启动、急需、清除和中断进程。函数收到
一个象SERVICE_CONTROL_PAUSE, SERVICE_CONTROL_CONTINUE, SERVICE_CONTROL_STOP,
SERVICE_CONTROL_INTERROGATE等操作码就需要为每种指令提供相应的处理步骤。
安装/反安装
要安装一个服务在系统注册时需要生成一些入口通常使用Windows有现成的API而不是注册函数来完成这些
步骤这些函数有CreateService()和DeleteService()。为了安装服务首先使用
OpenSCManager(NULL,NULL,SC_MANAGER_ALL_ACCESS)打开服务控制管理器SCM。然后调用CreateService()来建立服
务给出服务的名字如果要删除指定的服务也将需要使用这个名字删除。