我有这个片段:
#include <windows.h>
class Conf {
public:
Conf(int i) : m_i{ i } {
MessageBoxA(NULL, "Conf", "", MB_OK);
}
~Conf() {
MessageBoxA(NULL, "~Conf", "", MB_OK);
}
private:
int m_i;
};
Conf conf(26);
int WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstace,
PSTR pCmdLine,
int nCmdShow) {
MSG msg;
while (GetMessage(&msg, NULL, NULL, NULL)) {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
return 13;
}
当我运行可执行文件时,我立即收到带有文本
Conf
的消息框。但是,当程序停止时,例如通过任务管理器,我期望出现带有文本 ~Conf
的消息框,但没有得到任何结果。
如何将一些清理代码“挂钩”到我的可执行文件中,无论它如何停止,都可以运行?
任务管理器调用TerminateProcess(实际上),它将进程的所有线程标记为终止,回收系统资源,从内存中取消映射进程的代码等。从进程的角度来看,它是瞬时的。不再运行任何代码。并且进程无法阻止自身以这种方式终止。
(我说“实际上”是因为 TerminateProcess 是一个用户模式函数,在检查参数后,委托给 NtTerminateProcess,后者将控制权传递给 ZwTerminateProcess。如果任务管理器跳过 TerminateProcess 并直接调用较低的层,也就不足为奇了。 -级API。)
当用户想要注销或关闭机器时,Windows 会向正在运行的进程发出通知,并给予一点时间进行一些清理,但如果时间太长,它会突然终止它们。要获取通知,GUI 进程必须处理某些消息,并且控制台应用程序和系统服务必须注册用于关闭通知的控制处理程序。
我(可能不正确)的记忆是,很多旧版本的任务管理器会首先尝试一些更温和的方法来让进程自行关闭,然后再终止进程。例如,它可能首先将 WM_QUIT 消息发送到 GUI 应用程序的顶级窗口或触发控制台应用程序的 Ctrl+C 信号处理程序。如果申请很快就结束了,那就完成了。否则它会终止进程。
尽管在今天并不常见,但 DLL 可以保存其状态的单个副本,即使该 DLL 被加载到多个进程中也是如此。如果进程在 DLL 中执行调用时终止,则 DLL 的全局数据可能会处于不一致的状态,可能会导致其他进程出现问题。因此,尝试为进程提供有序退出的机会是值得的。