教你如何建立windows服务程序_第1页
教你如何建立windows服务程序_第2页
教你如何建立windows服务程序_第3页
教你如何建立windows服务程序_第4页
教你如何建立windows服务程序_第5页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、windows NT 与 Windows 9x 有一个非常重要的区别,即 Windows NT 提供了很多功能 强大的 Service( 服务) 。这些 Service 可以随着 NT的启动而自启动,也可以让用户通过控 制面板启动,还可以被 Win32 应用程序起停。甚至在没有用户登录系统的情况下,这些 Service 也能执行。许多 FTP、WWW服务器和数据库就是以 Service 的形式存在于 NT上,从 而实现了无人值守。就连最新版的“黑客”程序 Back Orifice 2000 也是以 Service 形式在 NT上藏身的。由于 Service 的编程较复杂,许多开发者想开发自己的

2、 Service 但往 往都望而却步。鉴于此,下面我们就从头到尾来构造一个全新的 Service ,读者只要在程序 中注明的地方加上自己的代码,那么就可以轻松拥有一个自己的 Service 。在编写 Service 之前,先介绍一下几个重要的函数: 1. SC_HANDLE OpenSCManager( LPCTSTR lpMachineName, LPCTSTR lpDatabaseName, DWORD dwDesiredAccess) OpenSCManager 函 数 打 开 指 定 计 算 机 上 的 service control manager database 。其中参数 lp

3、MachineName 指定计算机名, 若为空则指定为本机。 LpDatabaseName 为指定要 打开的 service control manager database 名, 默认 为空 。 dwDesiredAccess 指定操作的权限 , 可以为下面取值之一: SC_MANAGER_ALL_ACCESS / 所有权限 SC_MANAGER_CONNECT / 允许连接到 service control manager database SC_MANAGER_CREATE_SERVICE / 允许创建服务对象并把它加入 database SC_MANAGER_ENUMERATE_SER

4、VICE / 允许枚举 database 中的 Service SC_MANAGER_LOCK / 允许锁住 database SC_MANAGER_QUERY_LOCK_STATUS / 允许查询 database 的封锁信息 函数执行成功则返回一个指向 service control manager database 的句 柄,失败则返回 NULL。注意:WINNT通过一个名为 service control manager database 的数据库来管理所有的 Service ,因此对 Service 的任何操作都应打开此数据库。 2. SC_HANDLE CreateService(

5、SC_HANDLE hSCManager, LPCTSTR lpServiceName, LPCTSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCTSTR lpBinaryPathName, LPCTSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCTSTR lpDependencies, LPCTSTR lpServiceStartName, LPCTSTR lpPassword) Crea

6、tService 函数产生一个新的 SERVICE。其中参数 hSCManager 为指向 service control manager database 的句柄,由 OpenSCManager 返回。 LpServiceName 为 SERVICE的名字, lpDisplayName 为 Service 显示用名, dwDesiredAccess 是访问权限,本 程 序 中 用 SERVICE_ALL_ACCES。S wServiceType, 指 明 SERVICE 类 型 , 本 程 序 中 用 SERVICE_WIN32_OWN_PROCESS| SERVICE_INTERACTIV

7、E_PRO。CEdSwStartType 为 Service 启动方式,本程序采用自启动,即 dwStartType 等 于 SERVICE_AUTO_STAR。T dwErrorControl 说 明 当 Service 在 启 动 中 出 错 时 采 取 什 么 动 作 , 本 程 序 采 用 SERVICE_ERROR_IGNO即RE忽约错误, 读者可以改为其他的。 LpBinaryPathName 指明 Service 本体程序的路径名。剩下的五个参数一般可设为NULL。如函数调用成功则返回这个新 Service 的句柄,失败则返回 NULL。与此函数对应的是 DeleteServic

8、e( hService) ,它 删除指定的 Service 。 3. SC_HANDLE OpenService(SC_HANDLE hSCManager,LPCTSTR lpServiceName, DWORD dwDesiredAccess ) OpenService 函数打开指定的 Service 。其中参数 hSCManager 为指向 service control manager database 的句柄,由 OpenSCManager 返回。 LpServiceName 为 Service 的名字,dwDesiredAccess 是访问权限, 其可选值比较多, 读者可以参看 SD

9、K Help. 函数调用成功则返回打开的 Service 句柄,失败则返回 NULL。 4. BOOL StartService( SC_HANDLE hService, DWORD dwNumServiceArgs,LPCTSTR *lpServiceArgVectors ) StartService 函数启动指定的 Service 。其中参数 hService 为指向 Service 的 句 柄 , 由 OpenService 返 回 。 dwNumServiceAr 为 启 动 服 务 所 需 的 参 数 的 个 数 。 lpszServiceArgs 为 启 动 服务所需的参数。 函数

10、执行成功则返回 True, 失败 则返回 False 。 5. BOOL ControlService(SC_HANDLE hService DWORD dwControl,LPSERVICE_STATUS lpServiceStatus ) Service 程序没有专门的停止函数,而是用 ControlService 函数来控制 Service 的暂停、 继续、停止等操作。 参数 dwControl 指定发出的控制命令, 可以为以下几个值: SERVICE_CONTROL_STOP 停/ 止 Service SERVICE_CONTROL_PAUSE 暂/ 停 Service SERVICE

11、_CONTROL_CONTINUE继 / 续 Service SERVICE_CONTROL_INTERROGATE查 /询 Service 的状态 SERVICE_CONTROL_SHUTDOWN /让/ ControlService 调用失效 参数 lpServiceStatus 是一个指向 SERVICE_STATU的S 指针。 SERVICE_STATU是S 一 个比较重要的结构, 它包含了 Service 的各种信息, 如当前状态、 可接受何种控制命令等等。 6. BOOL QueryServiceStatus( SC_HANDLE hService,LPSERVICE_STATUS

12、 lpServiceStatus ) QueryServiceStatus 函数比较简单,它查询并返回当前 Service 的状态。 编制一个 Service 一般需要两个程序, 一个是 Service 本体,一个是用于对 Service 进行控制的控制程序。 通常 Service 本体是一个 console 程序, 而控制程序则是一个普通的 Win32 应用程序(当然,用户不用控制程序而通过控制面板也可对 Service 进行启、停,但 不能进行添加、删除操作。 ) 首先, 我们来编写 Service 本体。 对于 Service 本体来说, 它一般又由以下三部分 组成: main() 、

13、ServiceMain ()、Handler (),下面是 main() 的源代码:(注:由于篇幅的 关系,大部分程序都没进行错误处理,读者可以自己添上) int main(int argc, char *argv) SERVICE_TABLE_ENTRY ste2; / 一个 Service 进程可以有多个线程,这是每个 / 线程的入口表 ste0.lpServiceName= W.Z.SERVICE ; / 线程名字 ste0.lpServiceProc=ServiceMain; / 线程入口地址 ste1.lpServiceName=NULL; / 最后一个必须为 NULL ste1.l

14、pServiceProc=NULL; StartServiceCtrlDispatcher(ste); return 0; main() 是 Service 的主线程。当 servie control manager 开始一个 Service 进程时, 它总是等待这个 Service 去调用 StartServiceCtrlDispatcher ()函数。 main( ) 作为这个进程的主线程应该在程序开始后尽快调用 StartServiceCtrlDispatcher ()。 StartServiceCtrlDispatcher ()在被调用后并不立即返回, 它把本 Service 的主线程

15、连接 到 service control manager ,从而让 service control manager 通过这个连接发 送开始、 停止等控制命令给主线程。 主线程在这时就扮演了一个命令的转发器的角色, 它或 者 调 用 Handle() 去 处 理 停 止 、 继 续 等 控 制 要 求 , 或 者 产 生 一 个 新 线 程 去 执 行 ServiceMain 。 StartServiceCtrlDispatcher()在整个 Service 结束时才返回。 ServiceMain ()是 Service 真正的入口点,必须在 main() 中进行了正确的定义。 ServiceM

16、ain( ) 的两个参数是由 StartService ()传递过来的。下面是 ServiceMain() 的源代码: void WINAPI ServiceMain(DWORD dwArgc,LPTSTR *lpszArgv) ssh=RegisterServiceCtrlHandler ( W.Z.SERVICE ,Handler); ss.dwServiceType=SERVICE_WIN32_OWN _PROCESS|SERVICE_INTERACTIVE_PROCESS; ss.dwCurrentState=SERVICE_START_PENDING; / 如用户程序的代码比较多 (

17、执行时间超过 1 秒),这儿要设成 SERVICE_ START_PENDIN,G 待用户程序完成后再设为 SERVICE_RUNNIN。G ss.dwControlsAccepted=SERVICE_ACCEPT_ STOP;/ 表明 Service 目前能接受的命令是停止命令。 ss.dwWin32ExitCode=NO_ERROR; ss.dwCheckPoint=0; ss.dwWaitHint=0; SetServiceStatus(ssh, / 必须随时更新数据库中 Service 的状态。 Mycode(); / 这儿可放入用户自己的代码 ss.dwServiceType=SER

18、VICE_WIN32_OWN_ PROCESS|SERVICE_INTERACTIVE_PROCESS; ss.dwCurrentState=SERVICE_RUNNING; ss.dwControlsAccepted=SERVICE_ACCEPT_STOP; ss.dwWin32ExitCode=NO_ERROR; ss.dwCheckPoint=0; ss.dwWaitHint=0; SetServiceStatus(ssh, Mycode();/ 这儿也可放入用户自己的代码 在 ServiceMain ()中应该立即调用 RegisterServiceCtrlHandler ()注册一个

19、 Handler 去处理控制程序或控制面板对 Service 的控制要求。 Handler ()被转发器调用去处理要求, 下面是 Handler() 的源代码 : void WINAPI Handler(DWORD Opcode) switch(Opcode) case SERVICE_CONTROL_STOP: / 停止 Service Mycode ();/ 这儿可放入用户自己的相关代码 ss.dwWin32ExitCode = 0; ss.dwCurrentState =SERVICE_STOPPED; / 把 Service 的当前状态置为 STOP ss.dwCheckPoint =

20、 0; ss.dwWaitHint = 0; SetServiceStatus (ssh, / 必须随时更新数据库中 Service 的状态 break; case SERVICE_CONTROL_INTERROGATE: SetServiceStatus (ssh, / 必须随时更新数据库中 Service 的状态 break; 好了, Service 本体程序已基本完成, 我们接着来看一下 Service 的控制程序: 控制程序是一个标准的 window 程序,上面主要有四个按纽: Create Service 、 Delete Service 、 start 、stop ,分别用来产生、

21、删除、开始和停止Service 。下面是它 们的部分源代码: 1. 产生 Service void _fastcall TForm1:CreateBtnClick (TObject *Sender) scm=OpenSCManager(NULL,NULL, SC_MANAGER_CREATE_SERVICE); if (scm!=NULL) svc=CreateService(scm, W.Z.SERVICE , W.Z.SERVICE ,/Service 名字 SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS |SERVICE_INTERACTIVE

22、_PROCESS, SERVICE_AUTO_START, / 以自动方式开始 SERVICE_ERROR_IGNORE, C:ntservice.exe , /Service 本体程序路径, 必须与具体位置相符 NULL,NULL,NULL,NULL,NULL); if (svc!=NULL) CloseServiceHandle(svc); CloseServiceHandle(scm); 2. 删除 Service void _fastcall TForm1:DeleteBtnClick (TObject *Sender) scm=OpenSCManager(NULL,NULL, SC_MANAGER_CONNECT); if (scm!=NULL) svc=OpenService(scm, W.Z.SERVICE , SERVICE_ALL_ACCESS); if (svc!=NULL) QueryServiceStatus(svc, if (ServiceStatus.dwCurrentState= SERVICE_RUNNING)/删除前,先停止此 Service. ControlService(svc, SERVICE_CONTROL_STOP, DeleteService(svc); CloseServiceHand

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论