VC++ Service编程(六)Control Handler函数

Control Handler函数

    每个服务都有一个控制处理器,HandlerEx函数。当服务程序从一个服务控制程序那里收到一个控制请求时,HandlerEx函数就会被控制调度器调用。因此,这个函数运行在控制调度器的环境中。服务调用RegisterServiceCtrlHandler或者RegisterServiceCtrlHandlerEx函数来注册它的Control Handler(控制处理器)函数。
    任何时间调用HandlerEx,服务必须调用SetServiceStatus函数,向SCM(服务控制管理器)报告当前状态。不管状态改变与否,都必须这么做。
    服务控制程序可以利用ControlService来发送控制请求。所有的服务都必须接收并处理SERVICE_CONTROL_INTERROGATE控制码。你可以调用SetServiceStatus来设定接不接收其它的控制代码。要接收SERVICE_CONTROL_DEVICEEVENT控制码,你必须调用RegisterDeviceNotification函数。服务亦可以处理额外的用户定义的控制码。
    控制处理器必须在30秒内返回,否则SCM会返回一个错误。如果控制处理器在运行的同时,服务需要做一个较长的处理,就应该创建一个新的线程来做这个处理,然后返回。举个例子,长时间处理一个停止请求,创建一个新的线程来处理这个停止操作。控制处理器应该调用SetServiceStatus函数发送SERVICE_STOP_PENDING消息,然后返回。
    当用户关闭系统的时候,所有用SERVICE_ACCEPT_SHUTDOWN控制码调用过SetServiceStatus的控制处理器,都会收到SERVICE_CONTROL_SHUTDOWN控制码。所有的这些服务都会按照他们在已安装服务数据库中的顺序被通知到。在系统关闭之前,一个服务有大概20秒的默认时间来进行清理工作。这段时间过后,不管服务是否已经完全关闭,系统都会关闭。注意,如果系统进入关闭状态(不是重新启动或者电源关闭),服务继续运行。
    如果服务需要更多时间用来清理,它发送一个STOP_PENDING消息和一个等待时间,这样,服务控制器就知道要等多长时间,然后再向系统报告服务关闭完成。尽管这样,服务控制器等待的时间也是有限度的。可以更改注册表项HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControl中的WaitToKillServiceTimeout值来改变这个时间限制。
    顾客要求操作系统快速关闭。举个例子,使用UPS电源运转的计算机如果不在UPS能源耗尽之前关闭完,数据就会丢失。所以,服务应该尽可能快地完成清理工作。将为保存数据减到最少,在关闭时至保存为保存的数据是个好习惯。因为计算机正在关闭,千万不要在释放内存或别的系统资源上浪费时间。如果你要向服务器通知这在退出,把等待返回的时间减到最小,因为网络问题也有可能耽误你的服务关闭。
   注意,服务关闭过程中,SCM不会考虑从属关系。SCM注意清点正在运行的服务,并向它们发送SERVICE_CONTROL_SHUTDOWN命令。因此,一个服务可能会因另一个服务已经中止而运行失败。利用SetProcessShutdownParameters函数,来设置从属服务的关闭顺序。SCM通过这个函数给它的处理器赋予0x1E0优先级;当它的控制处理器被调用,SCM就发送SERVICE_CONTROL_SHUTDOWN通知,同时等待这些服务退出,然后从控制处理器里返回。
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
很高兴能够回答你的问题。首先,让我们来了解一下Windows服务是什么。 Windows服务是在Windows操作系统中以后台方式运行的应用程序。服务的主要作用是在系统启动时自动启动,并在后台持续运行以提供某种特定的功能或服务。Windows服务可以通过Windows服务管理器进行管理和控制。 接下来,我们来看一下如何实现一个Windows服务并进行安装和控制。 1. 创建Windows服务项目 首先,我们需要使用Visual Studio创建一个Windows服务项目。在Visual Studio中选择“新建项目”->“Visual C++”->“Windows Desktop”->“Windows服务”,然后命名项目并选择保存路径即可。 2. 编写服务代码 在服务项目中,我们需要编写服务代码。这些代码包括服务的启动、停止、暂停、恢复等功能。下面是一个示例代码: ``` #include "stdafx.h" #include "MyService.h" #include <iostream> using namespace std; #define SERVICE_NAME "MyService" SERVICE_STATUS ServiceStatus; SERVICE_STATUS_HANDLE hServiceStatusHandle; void WINAPI ServiceMain(DWORD argc, LPTSTR *argv); void WINAPI ServiceCtrlHandler(DWORD); int _tmain(int argc, _TCHAR* argv[]) { SERVICE_TABLE_ENTRY ServiceTable[] = { {SERVICE_NAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain}, {NULL, NULL} }; if (StartServiceCtrlDispatcher(ServiceTable) == FALSE) { cout << "StartServiceCtrlDispatcher failed" << endl; return GetLastError(); } return 0; } void WINAPI ServiceMain(DWORD argc, LPTSTR *argv) { hServiceStatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler); if (hServiceStatusHandle == NULL) { cout << "RegisterServiceCtrlHandler failed" << endl; return; } ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ServiceStatus.dwCurrentState = SERVICE_START_PENDING; ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; ServiceStatus.dwWin32ExitCode = NO_ERROR; ServiceStatus.dwServiceSpecificExitCode = 0; ServiceStatus.dwCheckPoint = 0; ServiceStatus.dwWaitHint = 0; if (SetServiceStatus(hServiceStatusHandle, &ServiceStatus) == FALSE) { cout << "SetServiceStatus failed" << endl; return; } ServiceStatus.dwCurrentState = SERVICE_RUNNING; if (SetServiceStatus(hServiceStatusHandle, &ServiceStatus) == FALSE) { cout << "SetServiceStatus failed" << endl; return; } while (ServiceStatus.dwCurrentState == SERVICE_RUNNING) { // Do something here } return; } void WINAPI ServiceCtrlHandler(DWORD dwCtrl) { switch (dwCtrl) { case SERVICE_CONTROL_PAUSE: ServiceStatus.dwCurrentState = SERVICE_PAUSE_PENDING; if (SetServiceStatus(hServiceStatusHandle, &ServiceStatus) == FALSE) { cout << "SetServiceStatus failed" << endl; return; } ServiceStatus.dwCurrentState = SERVICE_PAUSED; if (SetServiceStatus(hServiceStatusHandle, &ServiceStatus) == FALSE) { cout << "SetServiceStatus failed" << endl; return; } break; case SERVICE_CONTROL_CONTINUE: ServiceStatus.dwCurrentState = SERVICE_CONTINUE_PENDING; if (SetServiceStatus(hServiceStatusHandle, &ServiceStatus) == FALSE) { cout << "SetServiceStatus failed" << endl; return; } ServiceStatus.dwCurrentState = SERVICE_RUNNING; if (SetServiceStatus(hServiceStatusHandle, &ServiceStatus) == FALSE) { cout << "SetServiceStatus failed" << endl; return; } break; case SERVICE_CONTROL_STOP: ServiceStatus.dwCurrentState = SERVICE_STOP_PENDING; if (SetServiceStatus(hServiceStatusHandle, &ServiceStatus) == FALSE) { cout << "SetServiceStatus failed" << endl; return; } ServiceStatus.dwCurrentState = SERVICE_STOPPED; if (SetServiceStatus(hServiceStatusHandle, &ServiceStatus) == FALSE) { cout << "SetServiceStatus failed" << endl; return; } break; default: break; } } ``` 这是一个简单的示例代码,其中包含了服务的启动、停止、暂停和恢复功能。我们可以将服务的具体功能实现放在while循环中。 3. 安装服务 在编写完服务代码后,我们需要将服务安装到系统中。可以使用命令行工具“sc.exe”来进行安装。打开命令提示符窗口,输入以下命令: ``` sc create MyService binPath= "C:\MyService.exe" ``` 其中,MyService是服务的名称,C:\MyService.exe是服务的可执行文件路径。 4. 启动、停止、暂停和恢复服务 在服务安装成功后,我们可以使用Windows服务管理器来启动、停止、暂停和恢复服务。打开Windows服务管理器,找到MyService服务,右键单击服务并选择相应的选项即可。 除此之外,我们也可以使用命令行工具“sc.exe”来进行控制。以下是一些常用的命令: ``` sc start MyService sc stop MyService sc pause MyService sc continue MyService ``` 这些命令可以在命令提示符窗口中直接执行。 总结 通过以上步骤,我们可以成功地实现一个Windows服务,并进行安装和控制。请注意,在实现服务时,我们需要注意服务的生命周期、状态转换、错误处理等方面。希望这篇文章能够帮助你更好地理解Windows服务的实现和控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值