gpt4 book ai didi

c++ - 如何确保 Windows 2008 R2 将 SERVICE_CONTROL_PRESHUTDOWN 控制通知传递给服务

转载 作者:行者123 更新时间:2023-11-30 03:04:45 26 4
gpt4 key购买 nike

我正在使用纯 C++ 和 Windows API 编写服务,并希望它接收 Windows 2008 R2 提供的 PRESHUTDOWN 通知。

http://msdn.microsoft.com/en-us/library/windows/desktop/ms685996(v=vs.85).aspx

我希望此服务处理关机前事件并防止机器在任意时间内完成关机。

我的 ServiceMain 循环,每 5 秒注销一条消息。

我将 dwControlsAccepted 设置为:

SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN

我在我的 ServiceControl 回调中收到 SERVICE_CONTROL_STOP 通知就好了。

如果我运行我的服务,然后调用

sc query "MyService"

它说:

(STOPPABLE, NOT_PAUSABLE, ACCEPTS_PRESHUTDOWN)

我一收到任何服务控制通知就在日志文件中写入一个条目,甚至在我查看它是什么之前。

当我关机时,windows 会在屏幕上用大白字提示“Stopping MyService”,稍等片刻,然后完成关机。

但是:

主循环不断写入日志文件。日志文件不包含对任何服务控制尝试的引用。

然后 Windows 放弃关闭我的服务并将其杀死。

现在,如果我做完全相同的事情,但注册 SHUTDOWN 而不是 PRESHUTDOWN,我会在日志文件中看到我希望看到的所有通知(尽管不能延长关闭时间,因为我们可以'不要在 SHUTDOWN 通知中执行此操作)。

代码的唯一变化是删除了设置状态调用中​​的三个字母“PRE”。

我什至没有达到可以开始递增 dwCheckPoint 的地步 - Windows 子系统没有通知我。

Windows 知道我正在寻找预关机消息,如“sc query”所证明的那样,有什么可以阻止它接收预关机消息吗?

相关方法:

上报状态时(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 放弃并杀死它。

最佳答案

根据documentation , SERVICE_CONTROL_PRESHUTDOWN 仅发送到 extended callback .尝试使用 RegisterServiceCtrlHandlerEx .

关于c++ - 如何确保 Windows 2008 R2 将 SERVICE_CONTROL_PRESHUTDOWN 控制通知传递给服务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8388162/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com