[英]How to add PreShutdown event to ATL service?
I've inherited the C++ code for an old ATL based service which contains the basic structures from the old ATL wizards (_tWinMain(), Run(), RunMessageLoop() etc). 我已经为旧的基于ATL的服务继承了C ++代码,其中包含旧的ATL向导(_tWinMain(),Run(),RunMessageLoop()等)的基本结构。
In particular, this code already handles "Shutdown" and "Stop" events - and I've been asked to add an additional closedown item into the "PreShutdown" event. 特别是,这段代码已经处理了“ Shutdown”和“ Stop”事件-并且我被要求在“ PreShutdown”事件中添加一个额外的closedown项目。
I've added the SERVICE_ACCEPT_PRESHUTDOWN option.. 我添加了SERVICE_ACCEPT_PRESHUTDOWN选项。
m_status.dwControlsAccepted |= SERVICE_ACCEPT_PRESHUTDOWN
..but I can't see how to catch the resulting event - SERVICE_CONTROL_PRESHUTDOWN - as ATL appears to provide for "OnShutdown" and "OnClose" methods but doesn't contain an entry for "OnPreShutdown" that I can see. ..但我看不到如何捕获结果事件-SERVICE_CONTROL_PRESHUTDOWN-ATL似乎提供了“ OnShutdown”和“ OnClose”方法,但没有包含我看到的“ OnPreShutdown”条目。
Can anyone point me at something which will allow me to add an OnPreShutdown to my existing code? 谁能指出我可以使我在现有代码中添加OnPreShutdown的东西?
Implementing services using ATL is covered at ATL Services . ATL服务介绍了使用ATL实施服务 。 To handle control requests that a default ATL-generated service wouldn't, you need to extend the default-generated
Handler
implementation. 要处理默认ATL生成的服务不会处理的控制请求,您需要扩展默认生成的
Handler
实现。
This is a rough sketch for what you need to do (in addition to registering for the control request, which you already are): 这是您需要做的粗略草图(除了注册控制请求之外,您已经是):
void CMyServiceModule::Handler(DWORD dwOpcode) throw() {
if (SERVICE_CONTROL_PRESHUTDOWN == dwOpcode) {
// Perform custom handling
}
else {
// Pass all other control codes to default implementation
__super::Handler(dwOpcode);
}
}
As an alternative, you could override the OnUnknownRequest
member in your custom implementation. 或者,您可以在自定义实现中覆盖
OnUnknownRequest
成员。 This member is called for all codes that aren't handled by the default implementation: 对于默认实现未处理的所有代码,将调用此成员:
void CMyServiceModule::OnUnknownRequest(DWORD dwOpcode) {
if (SERVICE_CONTROL_PRESHUTDOWN == dwOpcode) {
// Perform custom handling
}
else {
// Possibly handle other control codes
}
}
The main problem is that ATL uses RegisterServiceCtrlHandler
instead of RegisterServiceCtrlHandlerEx
; 主要问题是ATL使用
RegisterServiceCtrlHandler
而不是RegisterServiceCtrlHandlerEx
; only the second of these actually registers for the SERVICE_CONTROL_PRESHUTDOWN
message. 这些中只有第二个实际注册了
SERVICE_CONTROL_PRESHUTDOWN
消息。 Further, ATL does not contain an inheritable template for OnPreShutdown(). 此外,ATL不包含OnPreShutdown()的可继承模板。
The solution is therefore in four parts: 因此,解决方案分为四个部分:
(1) Update the list of accepted control messages to include the SERVICE_ACCEPTED_PRESHUTDOWN
message. (1)更新接受的控制消息列表,以包括
SERVICE_ACCEPTED_PRESHUTDOWN
消息。 You can remove the SERVICE_ACCEPTED_SHUTDOWN
as Windows deems the service to be shut down once you have handled the Pre-Shutdown so you will never receive this message. 您可以删除
SERVICE_ACCEPTED_SHUTDOWN
因为一旦Windows处理您认为“关闭前”服务即被关闭,那么您将永远不会收到此消息。 In my case the change was to the list of controls set in the overridden PreMessageLoop()
method: 就我而言,更改是在覆盖的
PreMessageLoop()
方法中设置的控件列表:
I changed: m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
我更改了:
m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
To: m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN;
到:
m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN;
m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN;
However you may not have overridden this method - so you should simply change that list at whatever point you are setting this value. 但是,您可能没有重写此方法-因此您应该在设置此值的任何时候简单地更改该列表。 (IInspectable (see other answer) recommends considering the constructor.)
(IInspectable(请参阅其他答案)建议考虑构造函数。)
(2) Override ServiceMain()
, replacing it entirely by cloning the code and updating it to use RegisterServiceCtrlHandlerEx
. (2)覆盖
ServiceMain()
,通过克隆代码并将其更新为使用RegisterServiceCtrlHandlerEx
来完全替换它。 The key change is: 关键更改是:
Change: m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
更改:
m_hServiceStatus = RegisterServiceCtrlHandler(m_szServiceName, _Handler);
To: m_hServiceStatus = RegisterServiceCtrlHandlerEx(m_szServiceName, (LPHANDLER_FUNCTION_EX)_Handler, NULL);
若要:
m_hServiceStatus = RegisterServiceCtrlHandlerEx(m_szServiceName, (LPHANDLER_FUNCTION_EX)_Handler, NULL);
but you will also need to change references to pT
and T
to be this
in order to remove the templating code (you can also remove the line defining pT
); 但是您还需要将对
pT
和T
引用更改this
,以删除模板代码(也可以删除定义pT
的行); for example: 例如:
Change: hr = T::InitializeCom();
更改:
hr = T::InitializeCom();
To: hr = this->InitializeCom();
收件人:
hr = this->InitializeCom();
Do not include a call to the base class (as this would include a call to RegisterServiceCtrlHandler
). 不包括基类的调用(因为这将包括一个呼叫
RegisterServiceCtrlHandler
)。
(3) Override and extend Handler()
. (3)重写并扩展
Handler()
。 This requires the addition of new code such as: 这需要添加新的代码,例如:
void CServiceModule::Handler(_In_ DWORD dwOpcpde) throw()
{
switch (dwOpcode)
{
case SERVICE_CONTROL_PRESHUTDOWN:
this->OnPreShutdown();
break;
default:
__super::Handler(dwOpcode);
break;
}
}
(Thanks to IInspectable (see other answer) for helping point me in the right direction on this bit.) (感谢IInspectable(请参见其他答案),在此方面帮助我指出了正确的方向。)
(4) You can now implement an OnPreShutdown()
method: (4)您现在可以实现
OnPreShutdown()
方法:
void CServiceModule::OnPreShutdown() throw()
{
// custom handling code
// ...
// note: service must shutdown in this handler, so finish
// by notifying this to SCM.
SetServiceStatus(SERVICE_STOPPED);
}
Note that Windows expects the service to be stopped during the pre-shutdown if you use it, and once the above is implemented your service will not receive any SERVICE_CONTROL_SHUTDOWN
messages (as it should already be shut down). 请注意,如果您使用Windows,则希望该服务在预关闭期间停止,并且一旦实现了上述功能,您的服务将不会收到任何
SERVICE_CONTROL_SHUTDOWN
消息(因为它应该已经关闭)。 To allow Windows to carry on shutting other services down you therefore need to add a final SetServiceStatus(SERVICE_STOPPED)
call at the end of your OnPreShutdown()
method. 为了使Windows能够继续关闭其他服务,因此您需要在
OnPreShutdown()
方法的末尾添加一个最终的SetServiceStatus(SERVICE_STOPPED)
调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.