[英]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
我希望该服务处理关机前事件,并防止计算机在任意时间内完成关机。
我的ServiceMain循环,每5秒注销一条消息。
我将dwControls设置为:
SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN
我在ServiceControl回调中收到SERVICE_CONTROL_STOP通知就好了。
如果我运行我的服务,然后致电
sc query "MyService"
它说:
(STOPPABLE, NOT_PAUSABLE, ACCEPTS_PRESHUTDOWN)
我收到任何服务控制通知后立即写入日志文件的条目,然后我才会看到它是什么。
当我关机时,Windows会在屏幕上用大的白色字母说“停止MyService”,等待一下,然后完成关机。
然而:
主循环继续写入日志文件。 日志文件不包含任何服务控制尝试的引用。
然后,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 %d\n", dwCtrl);
switch(dwCtrl)
{
case SERVICE_CONTROL_PRESHUTDOWN:
{
LOG(eDeveloper10, L"ServiceCtrlHandler", L"Received SERVICE_CONTROL_PRESHUTDOWN\n");
ServiceReportStatus(SERVICE_STOP_PENDING, NO_ERROR, 10000);
// Signal the service to stop.
SetEvent(g_serviceStopEvent);
break;
}
}
}
它做的更多,但对于这个例子没什么用,因为我甚至没有看到日志(除非我注册SHUTDOWN)。
ServiceCtrlHandler总是快速返回,我在这里没有阻塞,我没有进入这里进行预关闭处理程序。 同时注册PRESHUTDOWN和SHUTDOWN也无济于事。 我已经在两台Windows 2008R2计算机,一台虚拟机,一台物理计算机上尝试了此方法,并且结果相同。 服务被编译为x64二进制文件。
有任何想法吗?
一些示例日志,这个日志是我请求收到SHUTDOWN的通知时:
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:\Windows\system32
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:\Windows\system32
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 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.