关于DLL和WM_QUERYENDSESSION中CTRL_SHUTDOWN_事件处理的混淆

关于DLL和WM_QUERYENDSESSION中CTRL_SHUTDOWN_事件处理的混淆,c,winapi,console,shutdown,C,Winapi,Console,Shutdown,我的UI在DLL中。现在,DLL和使用它的EXE都被编译为控制台程序,因此我可以在开发期间使用stdout和stderr进行调试和错误报告。其中一件事是我有一个uninit()函数来确保DLL没有泄漏内存 因此,我有一个由DLL设置的控件处理程序,CTRL\u LOGOFF\u EVENT和CTRL\u SHUTDOWN\u EVENT模拟用户单击文件菜单中的退出选项:它执行PostQuitMessage(0),清除代码发生在消息泵返回后 我知道通常不能忽略CTRL\u SHUTDOWN\u事件

我的UI在DLL中。现在,DLL和使用它的EXE都被编译为控制台程序,因此我可以在开发期间使用stdout和stderr进行调试和错误报告。其中一件事是我有一个
uninit()
函数来确保DLL没有泄漏内存

因此,我有一个由DLL设置的控件处理程序
CTRL\u LOGOFF\u EVENT
CTRL\u SHUTDOWN\u EVENT
模拟用户单击文件菜单中的退出选项:它执行
PostQuitMessage(0)
,清除代码发生在消息泵返回后

我知道通常不能忽略
CTRL\u SHUTDOWN\u事件
,程序将在处理程序例程返回后终止,不管它返回什么。但是根据

请注意,第三方库或DLL可以为您的应用程序安装控制台控制处理程序。如果这样做,该处理程序将覆盖默认处理程序,并在用户注销时导致应用程序退出

如果我读得正确,这说明DLL安装的控件处理程序会覆盖处理程序,从而在处理程序函数返回时导致程序退出。我错了吗?我的DLL的处理程序函数只返回
TRUE
,我假设这将进一步阻止任何其他默认值的运行,因为上面有一个提示

为什么??我注意到奇怪的行为:

在Windows Vista上,无论我做什么,程序都会关闭。在本例中,我想知道blurb是否错误,终止进程的处理程序是否仍在运行。无论我是否调用了
ShutdownBlockReasonCreate()
,这种情况都会发生

然而,在Windows7上,我的程序的主窗口似乎得到了一个
WM\u QUERYENDSESSION
,Windows会相应地响应它。这意味着,如果我在退出功能中说“不,还不退出(不要调用
PostQuitMessage(0)
”,Windows会弹出“应用程序正在阻止关机”屏幕,说我的主窗口正在阻止关机。在这种情况下,上面的简介似乎是正确的,因为程序在从控制台处理程序返回时没有退出(如果它被调用的话!)

如果我改为说“yes,call
PostQuitMessage(0)
,程序将正常退出。但是,我丢失了stdout和stderr上的调试输出,因此我无法判断它是否真的正常退出。将我的程序作为

new.exe > out.txt 2> err.txt
cmd.exe
上生成两个空文件;我不知道为什么在系统关闭时输出没有保存(谷歌搜索也没有显示任何信息)


那么,有人能帮我澄清我的困惑,让我实现这一点吗(包括
ShutdownBlockReasonCreate()
)正确吗?谢谢。

当您从注册的处理程序返回TRUE时,Windows会立即终止进程。当您返回FALSE时,会调用上一个处理程序。最终,这将是默认处理程序,它会立即终止进程

因此,您必须做的是在您满意之前不要返回和阻止。这需要与正在泵送消息循环的线程同步。您可以使用事件,泵送线程可以在其消息循环后调用SetEvent(),处理程序可以在调用PostQuitMessage()后调用WaitForSingleEvent()进行阻止

然而,这是一场线程竞赛,您的UI线程可能是由main()启动的,当main()返回时,CRT将终止程序。哪个线程将首先到达那里是不可预测的


感觉自己做错了什么?是的。控制台窗口不是显示调试输出的好方法。不知道为什么要这样做,但我知道你的工具链是不寻常的,我永远无法编译和运行你的任何代码片段。正确的方法是OutputDebugString()。该函数与调试器对话并使其显示文本。即使调试器无法显示此类文本,也可以回退到SysInternals的DebugView实用程序


您可能正在使用printf(),不喜欢修复所有调试语句,只需在CRT之前编写自己版本的链接,使用vprintf()和OutputDebugStringA().

是的,看看我是否做错了什么是导致这个问题的部分原因。我很好奇你不能编译我的示例。我现在的工具链是MinGW-w64,不过我尽量不使用任何特定的工具,我想让这个项目和其他一些项目可以用Microsoft的编译器(和其他)编译当然,值得研究。我会考虑切换到OutPuxDebug()。我使用控制台的主要原因是方便,稍后我会在开发中关掉控制台;直到那时我才能使用DbGVIEW(我已经有了它)。。谢谢。好的,我已经尝试过dbgview、windbg和gdb;它们都没有持续足够长的时间来告诉我在我的
PostQuitMessage(0)
(验证内存已被释放)之后的任何调试消息。这是系统关闭的预期不确定性吗?我是否应该麻烦测试这个边缘情况(系统关闭时正确清理我的库)?我想我之所以想这么做,是因为我作为一名图书馆作者有责任清理自己…嗯,不,没有什么好办法可以看到操作系统关闭时发生了什么。没关系,反正所有这些位都是gonzo。重要的是你对关闭做出反应,不这样做很容易看到。你只关心正确的操作在程序终止时进行清理,以便您有机会诊断泄漏。正常终止,而不是操作系统关闭时强制终止。好吧;那样的话,我就不用担心了。谢谢。(我仍然需要调查为什么我的代码示例在当前环境外无法工作…)