当前位置:天才代写 > tutorial > C语言/C++ 教程 > Windows处事编写道理及探讨(3)

Windows处事编写道理及探讨(3)

2017-11-06 08:00 星期一 所属: C语言/C++ 教程 浏览:422

副标题#e#

(三)对处事的深入接头之下

此刻我们还剩下一个函数可以在细节上接头,那就是处事的CtrlHandler函数。

当挪用RegisterServiceCtrlHandler函数时,SCM获得并生存这个回调函数的地点。一个SCP调一个汇报SCM如何去节制处事的Win32函数,此刻已经有10个预界说的节制请求:

Control code

Meaning

SERVICE_CONTROL_STOP Requests the service to stop. The hService handle must have SERVICE_STOP access.
SERVICE_CONTROL_PAUSE Requests the service to pause. The hService handle must have SERVICE_PAUSE_CONTINUE access.
SERVICE_CONTROL_CONTINUE Requests the paused service to resume. The hService handle must have SERVICE_PAUSE_CONTINUE access.
SERVICE_CONTROL_INTERROGATE Requests the service to update immediately its current status information to the service control manager. The hService handle must have SERVICE_INTERROGATE access.
SERVICE_CONTROL_SHUTDOWN Requests the service to perform cleanup tasks, because the system is shutting down. For more information, see Remarks.
SERVICE_CONTROL_PARAMCHANGE Windows 2000: Requests the service to reread its startup parameters. The hService handle must have SERVICE_PAUSE_CONTINUE access.
SERVICE_CONTROL_NETBINDCHANGE Windows 2000: Requests the service to update its network binding. The hService handle must have SERVICE_PAUSE_CONTINUE access.
SERVICE_CONTROL_NETBINDREMOVE Windows 2000: Notifies a network service that a component for binding has been removed. The service should reread its binding information and unbind from the removed component.
SERVICE_CONTROL_NETBINDENABLE Windows 2000: Notifies a network service that a disabled binding has been enabled. The service should reread its binding information and add the new binding.
SERVICE_CONTROL_NETBINDDISABLE Windows 2000: Notifies a network service that one of its bindings has been disabled. The service should reread its binding information and remove the binding.

上表中标有Windows 2000字样的就是2000中新添加的节制代码。除了这些代码之外,处事也可以接管用户界说的,范畴在128-255之间的代码。

当CtrlHandler函数收到一个SERVICE_CONTROL_STOP、SERVICE_CONTROL_PAUSE、 SERVICE_CONTROL_CONTINUE节制代码的时候,SetServiceStatus必需被挪用去确认这个代码,并指定你认为处事处理惩罚这个状态变革所需要的时间。

譬喻:你的处事收到了遏制请求,首先要把SERVICE_STATUS布局的dwCurrentState成员配置成SERVICE_STOP_PENDING,这样可以使SCM确定你已经收到了节制代码。当一个处事的暂停或遏制操纵正在执行的时候,必需指定你认为这种操纵所需要的时间:这是因为一个处事也许不能当即改变它的状态,它大概必需期待一个网络请求被完成可能数据被刷新到一个驱动器上。指按时间的要领就像我上一章说的那样,用成员dwCheckPoint和dwWaitHint来指明它完成状态改变所需要的时间。假如需要,可以用增加dwCheckPoint成员的值和配置dwWaitHint成员的值去指明你等候的处事达到下一步的时间的方法周期性的陈诉希望环境。

当整个启动的进程完成之后,要再一次挪用SetServiceStatus。这时就要把SERVICE_STATUS布局的dwCurrentState成员配置成SERVICE_STOPPED,当陈诉状态代码的同时,必然要把成员dwCheckPoint和dwWaitHint配置为0,因为处事已经完成了它的状态变革。暂停或继承处事的时候要领也一样。

当CtrlHandler函数收到一个SERVICE_CONTROL_INTERROGATE节制代码的时候,处事将简朴的将dwCurrentState成员配置成处事当前的状态,同时,把成员dwCheckPoint和dwWaitHint配置为0,然后再挪用SetServiceStatus就可以了。

在操纵系统封锁的时候,CtrlHandler函数收到一个SERVICE_CONTROL_SHUTDOWN节制代码。处事基础无须回应这个代码,因为系统即将封锁。它将执行生存数据所需要的最小动作集,这是为了确定呆板能实时封锁。缺省时系统只给很少的时间去封锁所有的处事,MSDN内里说或许是20秒的时间,不外那大概是Windows NT 4的配置,在我的Windows 2000 Server里这个时间是10秒,你可以手动的修改这个数值,它被记录在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control子键内里的WaitToKillServiceTimeout,单元是毫秒。

Windows办事编写原理及探讨(3)


#p#副标题#e#
#p#分页标题#e#

当CtrlHandler函数收到任何用户界说的代码时,它应该执行期望的用户自界说动作。除非用户自界说的动作要强制处事去暂停、继承或遏制,不然不调SetServiceStatus函数。假如用户界说的动作强迫处事的状态产生变革,SetServiceStatus将被挪用去配置dwCurrentState、dwCheckPoint和dwWaitHint,详细节制代码和前面说的一样。

假如你的CtrlHandler函数需要很长的时间执行操纵的话,千万要留意:如果CtrlHandler函数在30秒内没有返回的话,SCM将返回一个错误,这不是我们所期望的。所以假如呈现上述环境,最好的步伐是再成立一个线程,让它去继承执行操纵,以便使得CtrlHandler函数可以或许迅速的返回。譬喻,当收到一个SERVICE_CONTROL_STOP请求的时候,就像上面说的一样,处事大概正在期待一个网络请求被完成可能数据被刷新到一个驱动器上,而这些操纵所需要的时间是你不能预计的,那么就要成立一个新的线程期待操纵完成后执行遏制呼吁,CtrlHandler函数在返回之前仍然要陈诉SERVICE_STOP_PENDING状态,当新的线程执行完操纵之后,再由它将处事的状态配置成SERVICE_STOPPED。假如当前操纵的时间可以预计的到就不要这样做,仍然利用前面交待的要领处理惩罚。

CtrlHandler函数我就先讲这些,下面说说处事怎么安装。一个处事措施可以利用CreateService函数将处事的信息添加到SCM的数据库。

SC_HANDLE CreateService( SC_HANDLE hSCManager, // handle to SCM database LPCTSTR lpServiceName, // name of service to start LPCTSTR lpDisplayName, // display name DWORD dwDesiredAccess, // type of access to service DWORD dwServiceType, // type of service DWORD dwStartType, // when to start service DWORD dwErrorControl, // severity of service failure LPCTSTR lpBinaryPathName, // name of binary file LPCTSTR lpLoadOrderGroup, // name of load ordering group LPDWORD lpdwTagId, // tag identifier LPCTSTR lpDependencies, // array of dependency names LPCTSTR lpServiceStartName, // account name LPCTSTR lpPassword // account password );

hSCManager是一个标示SCM数据库的句柄,可以简朴的通过挪用OpenSCManager获得。

SC_HANDLE OpenSCManager( LPCTSTR lpMachineName, // computer name LPCTSTR lpDatabaseName, // SCM database name DWORD dwDesiredAccess // access type );

lpMachineName是方针呆板的名字,还记得我在第一章里说过可以在其它的呆板上面安装处事吗?这就是实现的要领。对方呆板名字必需以“\\”开始。假如通报NULL可能一个空的字符串的话就默认是本机。

lpDatabaseName是方针呆板上面SCM数据库的名字,但MSDN内里说这个参数要默认的配置成SERVICES_ACTIVE_DATABASE,假如通报NULL,就默认的打开SERVICES_ACTIVE_DATABASE。所以我还没有真的搞大白这个参数的存在意义,总之利用的时候通报NULL就行了。

dwDesiredAccess是SCM数据库的会见权限,详细值见下表:

Object access

Description

SC_MANAGER_ALL_ACCESS Includes STANDARD_RIGHTS_REQUIRED, in addition to all of the access types listed in this table.
SC_MANAGER_CONNECT Enables connecting to the service control manager.
SC_MANAGER_CREATE_SERVICE Enables calling of the CreateService function to create a service object and add it to the database.
SC_MANAGER_ENUMERATE_SERVICE Enables calling of the EnumServicesStatus function to list the services that are in the database.
SC_MANAGER_LOCK Enables calling of the LockServiceDatabase function to acquire a lock on the database.
SC_MANAGER_QUERY_LOCK_STATUS Enables calling of the QueryServiceLockStatus function to retrieve the lock status information for the database.

#p#分页标题#e#

想要得到会见权限的话,好像没那么巨大。MSDN内里说所有历程都被答允得到对所有SCM数据库的SC_MANAGER_CONNECT, SC_MANAGER_ENUMERATE_SERVICE, and SC_MANAGER_QUERY_LOCK_STATUS权限,这些权限使得你可以毗连SCM数据库,列举方针呆板上安装的处事和查询方针数据库是否已被锁住。但假如要建设处事,首先你需要拥有方针呆板的打点员权限,一般的通报SC_MANAGER_ALL_ACCESS就可以了。这个函数返回的句柄可以被CloseServiceHandle函数封锁。

lpServiceName是处事的名字,lpDisplayName是处事在“处事”打点东西里显示的名字。

dwDesiredAccess也是会见的权限,有一个比上面的还长的多的一个表,列位本身查MSDN吧。我们要安装处事,仍然简朴的通报SC_MANAGER_ALL_ACCESS。

dwServiceType是指你的处事是否和其它的历程相关联,一般是SERVICE_WIN32_OWN_PROCESS,暗示反面任何历程相关联。假如你确认你的处事需要和某些历程相关联,就配置成SERVICE_WIN32_SHARE_PROCESS。当你的处事要和桌面相关联的时候,需要配置成SERVICE_INTERACTIVE_PROCESS。

dwStartType是处事的启动方法。处事有三种启动方法,别离是“自动(SERVICE_AUTO_START)”“手动(SERVICE_DEMAND_START)”和“禁用(SERVICE_DISABLED)”。在MSDN里尚有别的的两种方法,不外是专为驱动措施配置的。

dwErrorControl抉择处事假如在系统启动的时候启动失败的话要怎么办。

意义

SERVICE_ERROR_IGNORE 启动措施记录错误产生,但继承启动。
SERVICE_ERROR_NORMAL 启动措施记录错误产生,并弹出一个动静框,但仍继承启动
SERVICE_ERROR_SEVERE 启动措施记录错误产生,假如是以last-known-good configuration启动的话,启动会继承。不然会以last-known-good configuration从头启动计较机。
SERVICE_ERROR_CRITICAL 启动措施记录错误产生,假如大概的话。假如是以last-known-good configuration启动的话,启动会失败。不然会以last-known-good configuration从头启动计较机。好严重的错误啊。

lpBinaryPathName是处事措施的路径。MSDN内里出格提到假如处事路径内里有空格的话必然要将路径用引号引起来。譬喻"d:\\my share\\myservice.exe"就必然要指定为"\"d:\\my share\\myservice.exe\""。

lpLoadOrderGroup的意义在于,假如有一组处事要凭据必然的顺序启动的话,这个参数用于指定一个组名用于符号这个启动顺序组,不外我还没有用过这个参数。你的处事假如不属于任何启动顺序组,只要通报NULL可能一个空的字符串就行了。

lpdwTagId是应用了上面的参数之后要指定的值,专用于驱动措施,与本文内容无关。通报NULL。

lpDependencies标示一个字符串数组,用于指明一串处事的名字可能一个启动顺序组。当与一个启动顺序构成立关联的时候,这个参数的寄义就是只有你指定的启动顺序组里有至少一个颠末对整个组里所有的成员已经全部实验过启动后,有至少一个成员乐成启动,你的处事才气启动。不需要成立依存干系的话,仍是通报NULL可能一个空的字符串。但假如你要指定启动顺序组的话,必需为组名加上SC_GROUP_IDENTIFIER前缀,因为组名和处事名是共享一个定名空间的。

lpServiceStartName是处事的启动账号,假如你配置你的处事的关联范例是SERVICE_WIN32_OWN_PROCESS的话,你需要以DomainName\UserName的名目指定用户名,假如这个账户在你本机的话,用.\UserName就可以指定。假如通报NULL的话,会以当地的系统账户登岸。假如是Win NT 4.0或更早的版本的话,假如你指定了SERVICE_WIN32_SHARE_PROCESS,就必需通报.\System指定处事利用当地的系统账户。最后,假如你指定了SERVICE_INTERACTIVE_PROCESS,你必需使处事运行在本机系统账户。

看名字就知道了,lpPassword是账户的暗码。假如指定系统账户的话,通报NULL。假如账户没有暗码的话,通报空字符串。

#p#分页标题#e#

总之处事的根基道理就是这样子了,到了这里这篇文章好像可以告一段落了,但实际上尚有许多内容必需要接头,所以我还不能草草收笔,敬请存眷下一章。

 

    关键字:

天才代写-代写联系方式