Windows服務

news/2024/7/7 13:05:51
Windows服务是其实一种特殊的二进制可执行文件,后缀名一般为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[]={{"gkeyService",gkeyServiceMain},{NULL,NULL}};      
          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()来建立服务,给出服务的名字,如果要删除指定的服务,也将需要使用这个名字删除。  
   
  例子代码如下:  
  //   创建服务  
  String   strSrvName   =   Application->ExeName;  
  SC_HANDLE   schService   =   CreateService(  
                  scm,  
                  "ccrunSrv",                       //   服务名称  
                  "ccrun's   Service",         //   服务详细说明  
                  SERVICE_ALL_ACCESS,  
                  SERVICE_WIN32_OWN_PROCESS   |   SERVICE_INTERACTIVE_PROCESS,  
                  SERVICE_AUTO_START,       //   以自动方式开始  
                  SERVICE_ERROR_NORMAL,  
                  strSrvName.c_str(),       //   Service本体程序路径,必须与具体位置相符  
                  NULL,  
                  NULL,  
                  NULL,  
                  NULL,  
                  NULL);  
  if(schService   !=   NULL)  
  {  
          CloseServiceHandle(schService);  
  }  
  //---------------------------------------------------------------------------  
  //   开始Service  
  sHandle   =   OpenService(scm,   "ccrunSrv",   SERVICE_START);  
  if(sHandle!=NULL)  
  {  
          StartService(sHandle,   0,   NULL);  
          CloseServiceHandle(sHandle);  
  }  
  //---------------------------------------------------------------------------  
  //   关闭服务管理器  
  CloseServiceHandle(scm);  
 
Top
2楼  nalichina   (Belina) 一级用户 该版得分小于等于100分  回复于 2004-06-07 09:25:34  得分 0

●   3.   如何控制WinNT下的服务   ●  
  ----在WindowsNT下   各种Service都存在service   control   manager   database中   因此我们可以通过对service   control   manager   database进行操作来实现对Service的编程。下面介绍常用的函数:  
   
  1:SC_HANDLE   OpenSCManager(LPCTSTR   lpszMachineName,   LPCTSTR   lpszDatabaseName,   DWORD   fdwDesiredAccess)    
  ----Open   SCManager   函数打开指定计算机上的service   control   manager   database。其中参数lpszMachineName指定计算机名   若为空则指定为本机。参数lpszDatabaseName指定要打开的service   control   manager   database,默认为空。  
   
  ----参数fdwDesiredAccess指定操作的权限,可以为下面取值之一  
  SC_MANAGER_ALL_ACCESS                 //   所有权限  
  SC_MANAGER_CONNECT                       //   允许连接service   control   manager  
  SC_MANAGER_CREATE_SERVICE         //   允许创建服务对象并把它加入service   control   manager   database  
  SC_MANAGER_ENUMERATE_SERVICE   //   允许枚举service   control   manager   database中的服务  
  SC_MANAGER_LOCK                             //   允许锁住service   control   manager   database  
  SC_MANAGER_QUERY_LOCK_STATUS   //   允许获取servicecontrolmanagerdatabase的封锁信息  
   
  ----函数返回值:函数执行成功则返回一个指向service   control   manager   database的句柄   失败则返回NULL。  
   
  2:SC_HANDLE   OpenService(SC_HANDLE   schSCManager,   LPCTSTR   lpszServiceName,   DWORD   fdwDesiredAccess)    
  ----OpenService函数打开指定的Service。  
  ----其中参数schSCManager是指向service   control   manager   database的句柄   由OpenSCManager函数返回。  
  ----参数lpszServiceName要打开的服务的名字   注意大小写。  
  ----参数fdwDesiredAccess指定操作的权限,可以为下面取值之一  
  SERVICE_ALL_ACCESS                         //   所有权限  
  SERVICE_CHANGE_CONFIG                   //   允许更改服务的配置  
  SERVICE_ENUMERATE_DEPENDENTS     //   允许获取依赖于该服务的其他服务  
  SERVICE_INTERROGATE                       //   允许立即获取服务状态  
  SERVICE_PAUSE_CONTINUE                 //   允许暂停和唤醒服务  
  SERVICE_QUERY_CONFIG                     //   允许获取服务配置  
  SERVICE_QUERY_STATU                       //   允许通过访问service   control   manager获取服务状态  
  SERVICE_START                                   //   允许启动服务  
  SERVICE_STOP                                     //   允许停止服务  
  SERVICE_USER_DEFINE_CONTROL       //   允许用户指定特殊的服务控制码  
  ----函数返回值:函数执行成功则返回指向某项服务的句柄   失败则返回NULL。  
   
  3:BOOL   QueryServiceStatus(SC_HANDLE   schService,LPSERVICE_STATUS   lpssServiceStatus)    
  ----QueryServiceStatus函数返回指定服务的当前状态。  
  ----其中参数schService是指向某项服务的句柄   由OpenService函数返回   且必须SERVICE_QUERY_STATUS的权限。  
  ----参数lpssServiceStatus中存放返回的服务状态信息   结构如下  
  typedef   struct   _SERVICE_STATUS  
  {  
          DWORD   dwServiceType                           //   服务类型  
          DWORD   dwCurrentState                         //   当前状态  
          DWORD   dwControlsAccepted                 //   服务可接受的控制码  
          DWORD   dwWin32ExitCode                       //   Win32出错代码  
          DWORD   dwServiceSpecificExitCode   //   服务出错代码  
          DWORD   dwCheckPoint                             //   用于跟踪服务长时间操作  
          DWORD   dwWaitHint                                 //   服务某一操作的最大允许时间,以毫秒为单位  
  }SERVICE_STATUS,   *LPSERVICE_STATUS;  
  ----函数返回值:函数执行成功则返回True,失败则返回False。  
   
  4:BOOLStartService(SC_HANDLE   schService,   DWORD   dwNumServiceArgs,   LPCTSTR   *   lpszServiceArgs)    
  ----StartService函数启动指定的服务。  
  ----其中参数schService是指向某项服务的句柄   由OpenService函数返回   且必须有SERVICE_START的权限。  
  ----dwNumServiceArgs为启动服务所需的参数的个数。  
  ----lpszServiceArgs为启动服务所需的参数。函数返回值:函数执行成功则返回True,失败则返回False。  
   
  5:BOOL   ControlService(SC_HANDLE   hService,   DWORD   dwControl,   LPSERVICE_STATUS   lpServiceStatus)    
  ----ControlService函数向Win32service发送控制码。  
  ----其中参数hService是指向某项服务的句柄   由OpenService函数返回。  
  ----参数dwControl为控制码   常用的有  
          SERVICE_CONTROL_STOP                 //   停止服务  
          SERVICE_CONTROL_PAUSE               //   暂停服务  
          SERVICE_CONTROL_CONTINUE         //   唤醒暂停的服务  
          SERVICE_CONTROL_INTERROGATE   //   刷新某服务的状态  
  ----参数lpServiceStatus指向SERVICE_STATUS结构   用于存放该服务最新的状态信息。  
  ----函数返回值:函数执行成功则返回True,失败则返回False。  
   
  6:BOOL   EnumServicesStatus(SC_HANDLE   hSCManager,   DWORD   dwServiceType,   DWORD   dwServiceState,  
                                                        LPENUM_SERVICE_STATUS   lpServices,   DWORD   cbBufSize,   LPDWORD   pcbBytesNeeded,  
                                                        LPDWORD   lpServicesReturned,   LPDWORD   lpResumeHandle)    
  ----EnumServicesStatus函数用于枚举NT下存在的Service。  
  ----其中参数hSCManager是指向service   control   manager   database的句柄   由OpenSCManager函数返回   且必须有SC_MANAGER_ENUMERATE_SERVICE的权限。  
  ----参数dwServiceType指定按服务的类型枚举。  
  ----参数dwServiceState指定按服务的状态枚举。  
  ----参数lpServices指向ENUM_SERVICE_STATUS结构   用于存放返回的服务的名字和状态信息。  
  ----参数cbBufSize返回参数lpServices的长度   以字节为单位。  
  ----参数pcbBytesNeeded返回获取剩余的Service所需字节的个数。  
  ----参数lpServicesReturned返回服务的个数。  
  ----参数lpResumeHandle   当第一次调用时该参数为0   当该函数再次被调用以获取另外的信息时   该参数表示下一个被读的Service。  
  ----函数返回值:函数执行成功则返回True,失败则返回False。  
  ----值得注意的是通常情况下该函数返回的结果为FALSE   我们可以调用GetLastError()来获取进一步信息。因为一台机器上有多种服务存在   所以GetLastError()应为ERROR_MORE_DATA   此时应再次调用EnumServicesStatus函数以获取正确的Service列表。  
 

转载于:https://www.cnblogs.com/janmson/archive/2006/05/24/407729.html


http://www.niftyadmin.cn/n/3337995.html

相关文章

电子不停车收费系统(ETC)专题(1)——系统概述

我国道路交通普遍较为拥堵已经在国人的脑海中留下了深刻的印象,每当车辆通过收费站时都要停下来缴费,既耽误了司机和乘客的时间,又消耗了交通管理部门的人力、物力和财力,更重要的时候,加剧了交通拥挤。因此&#xff0…

我们为什么使用ORM?

博客园在推广ORM方面的确做了很大的贡献,很多的程序员开始使用ORM,不用写SQL的喜悦让他们激动不已,可是好景不长,他们很快发现众多的烦恼一个接一个的出现了。很遗憾,我并不打算在这篇文章中解决这些问题,因…

电子不停车收费系统(ETC)专题(2)——国内现状

我国从90年代中后期引入该系统,并形成了第一次试点建设热潮。当时在江苏、广东、北京、福建等地有小规模试点应用,但是总体应用效果不好,大部分系统没能开通或成功运营。这一阶段的ETC系统建设多是以技术为驱动,盲目求新是很大的驱…

Foxmail 6.0 Beta4

Foxmail是优秀的国产电子邮件客户端软件。新的Foxmail具备强大的反垃圾邮件功能。数字签名和加密功能在Foxmail 新版中得到支持,可以确保电子邮件的真实性和保密性。 通过安全套接层(SSL)协议收发邮件使得在邮件接收和发送过程中,传输的数据都经过严格的…

电子不停车收费系统(ETC)专题(3)——技术探讨(1)

ETC系统作为未来智能交通发展的主要趋势之一,可以极大地促进我国公路交通收费的发展并且还能大大改善我国公路交通状况。然而由于ETC系统的建设投资巨大,区域联网收费情况错综复杂,造成我国ETC的发展并不顺利。本文提出采用只读RFID车辆识别技…

linux 用户打开进程数和文件数调整

1 查看nproc(max user processes)命令 [rootvm-cdh4 ~]# ulimit -u 14866 2 修改nproc 临时修改, 重登录或重启后失效: [rootvm-cdh4 ~]# ulimit -u 32768[rootvm-cdh4 ~]# ulimit -u 32768 尝试在 /etc/security/limits.conf 中加入下面的配置: * soft nproc 32768 …

电子不停车收费系统(ETC)专题(4)——技术探讨(2)

电子停车不收费系统,顾名思义就知道该系统一定与电子电路密切相关,ETC采用了大里集成电路的设备,端口防御雷电等脉冲电压、电流的能力下降,出现雷雨等高压脉冲损坏设备端口,故障率提高。本文主要介绍ETC收费车道的防雷…

H3 BPM让天下没有难用的流程之功能介绍

H3 BPM功能地图如下: 图:H3 BPM 功能地图 一、流程引擎 H3 BPM 流程引擎遵循WFMC 标准的工作流引擎技术,设计可运行的流程和表单,实现工作任务在人与人、人与系统、系统与系统之间自动流转执行。 图:H3 流程设计器 H3…