如何确保Windows 2008 R2将SERVICE_CONTROL_PRESHUTDOWN控制通知传递给服务?
How can I ensure that Windows 2008 R2 will pass the SERVICE_CONTROL_PRESHUTDOWN control notification to a service
我正在使用普通c++和windows API编写一个服务,并希望它能够接收windows 2008 R2中可用的PRESHUTDOWN通知。
http://msdn.microsoft.com/en-us/library/windows/desktop/ms685996 (v = vs.85) . aspx
我希望这个服务处理预关机事件,并防止机器在任意时间内完成关机。
My ServiceMain循环,每5秒注销一条消息。
我将dwControlsAccepted设置为:
SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN
我在我的ServiceControl回调中收到SERVICE_CONTROL_STOP通知。
如果我运行我的服务,并调用
sc query "MyService"
它说:
(STOPPABLE, NOT_PAUSABLE, ACCEPTS_PRESHUTDOWN)
在我收到任何服务控制通知之前,我就会在日志文件中写入一个条目。
当我关机时,windows会在屏幕上用白色的大字显示"正在停止我的服务",并等待一会儿,然后完成关机。
然而:主循环继续写入日志文件。日志文件不包含任何服务控制尝试的引用。
然后windows放弃关闭我的服务,直接杀死它。
现在,如果我做完全相同的事情,但注册SHUTDOWN而不是PRESHUTDOWN,我看到日志文件中我期望看到的所有通知(尽管不能延长关机期,因为我们不能从关机通知中做到这一点)。
代码的唯一变化是删除了设置状态调用中的三个字母"PRE"。
我甚至没有达到我可以开始增加dwCheckPoint的点- windows子系统没有通知我。
Windows知道我正在寻找预关机消息,如"sc查询"所证明的,是否有什么可以阻止它接收预关机消息?
相关方法:报告状态时(SCM报告服务已启动,非常愉快)
VOID ServiceReportStatus (DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
{
// Fill in the SERVICE_STATUS structure.
g_serviceStatus.dwCurrentState = dwCurrentState;
g_serviceStatus.dwWin32ExitCode = dwWin32ExitCode;
g_serviceStatus.dwWaitHint = dwWaitHint;
switch(dwCurrentState)
{
case SERVICE_START_PENDING:
case SERVICE_STOP_PENDING:
case SERVICE_CONTINUE_PENDING:
case SERVICE_PAUSE_PENDING:
g_serviceStatus.dwControlsAccepted = 0;
break;
default:
g_serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN;
}
// Report the status of the service to the SCM.
SetServiceStatus (g_serviceStatusHandle, &g_serviceStatus);
}
当我收到消息时:
VOID WINAPI ServiceCtrlHandler (DWORD dwCtrl)
{
LOG(eDeveloper10, L"ServiceCtrlHandler", L"Decoding SvcControl %dn", dwCtrl);
switch(dwCtrl)
{
case SERVICE_CONTROL_PRESHUTDOWN:
{
LOG(eDeveloper10, L"ServiceCtrlHandler", L"Received SERVICE_CONTROL_PRESHUTDOWNn");
ServiceReportStatus(SERVICE_STOP_PENDING, NO_ERROR, 10000);
// Signal the service to stop.
SetEvent(g_serviceStopEvent);
break;
}
}
}
它做了更多的事情,但在这个例子中没有什么用处,因为我甚至没有看到日志(除非我注册为SHUTDOWN)。
ServiceCtrlHandler总是很快返回,我没有在这里阻塞,我没有进入这里的预关闭处理程序。注册PRESHUTDOWN和SHUTDOWN也没有帮助。我在两台Windows 2008R2机器上进行了测试,一台是虚拟机,一台是物理机,结果是一样的。服务被编译为x64二进制文件。
任何想法?
一些示例日志,这个日志是当我请求被通知关机时:
L0 T2672 2781140 [CDbgEntry::LoadSystemDetails()] System Details Follow:
Computer Name : \****
Domain/Workgroup : **** [Domain]
User Name : SYSTEM
Operating System : Windows NT Version 6.1 Build 7600
Service Pack : None.
Terminal Services : Terminal Services Present
System Root : C:Windowssystem32
User's Windir : C:Windows
This file is recording debug messages with a maximum level of 10
L10 T2672 2781140 [ServiceInitialize] Service initialised, waiting for stop event
L10 T2672 2786140 [ServiceInitialize] Still waiting for stop event.
L10 T2668 2789328 [ServiceCtrlHandler] Decoding SvcControl 5
L10 T2668 2789328 [ServiceCtrlHandler] Received SERVICE_CONTROL_SHUTDOWN
L10 T2672 2789328 [ServiceInitialize] Stop event detected
L10 T2672 2789328 [ServiceInitialize] Blocking service shutdown
L10 T2672 2790328 [ServiceInitialize] Blocking service shutdown
L10 T2672 2791328 [ServiceInitialize] Blocking service shutdown
L10 T2672 2792328 [ServiceInitialize] Blocking service shutdown
L10 T2672 2793328 [ServiceInitialize] Blocking service shutdown
L10 T2672 2794328 [ServiceInitialize] Blocking service shutdown
L10 T2672 2795437 [ServiceInitialize] Blocking service shutdown
L10 T2672 2796437 [ServiceInitialize] Blocking service shutdown
请注意,在这种特殊情况下,阻塞服务关闭是正确的行为。
如果我注册PRESHUTDOWN,我从ServiceCtrlHandler根本得不到任何东西:
L0 T2244 516625 [CDbgEntry::LoadSystemDetails()] System Details Follow:
Computer Name : \****
Domain/Workgroup : **** [Domain]
User Name : SYSTEM
Operating System : Windows NT Version 6.1 Build 7600
Service Pack : None.
Terminal Services : Terminal Services Present
System Root : C:Windowssystem32
User's Windir : C:Windows
This file is recording debug messages with a maximum level of 10
L10 T2244 516453 [ServiceInitialize] Service initialised, waiting for stop event
L10 T2244 521625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 526625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 531625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 536625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 541625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 546625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 551625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 556625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 561625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 566625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 571625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 576625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 581625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 586625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 591625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 596625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 601625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 606625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 611625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 616625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 621625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 626625 [ServiceInitialize] Still waiting for stop event.
L10 T2244 631625 [ServiceInitialize] Still waiting for stop event.
没有任何事件,直到windows放弃并杀死它。
根据文档,SERVICE_CONTROL_PRESHUTDOWN只发送到扩展回调。尝试使用RegisterServiceCtrlHandlerEx.
- 控制允许动态运行c++的并发操作数
- 从控制台中删除最后打印的元素
- 是否可以使用if constexpr删除控制流语句
- 无法在windows控制台中为C++程序提供必要的输入
- 控制到达非空函数clang(-Wreturn-type)的末尾
- 查找 GCD:并非所有控制路径都返回值
- 通过 API 控制 DJI 相机
- 禁止在控制台上记录谷神星
- 是否可以使用一个类来控制 C++ 中另一个类的对象?(阿杜伊诺)
- 如何删除列出的"QGraphicsPathItem"对象以控制进程内存使用情况?
- 我在 C++ 代码中遇到错误警告:控制到达非空函数 [-Wreturn 类型] 的末尾
- C++ Python 模块在 Blender 中崩溃,但在 Python 控制台中不会崩溃
- wx通用目录控制错误"wxTheFileIconsTable was nullptr"
- main() 中的 std::cout 在调试期间不会在调试控制台中打印任何内容
- Cython通过浮点数的最快方式,用于高频控制回路
- 用户控制从 c++ 到 java 脚本的 Webassembly 访问调用
- C ++,如何从控制台中输入的字符串中删除字母?
- 如何从单独的线程控制 SFML 窗口?
- 如何防止 Windows 控制台上的回车键自动滚动
- 我们能否在stm32f中使用硬件定时器控制两个独立的进程