如何在 Windows 控制臺程序捕捉關閉消息

#C# #C++ #Windows #Console

有时候我们会写一些常驻系统的控制台程序。虽然一般可以直接关闭,但有时候我们需要在关闭前释放一些系统资源或通知。那么就需要捕捉其关闭的消息。这个时候,我们就可以用 Windows 的 Console API SetConsoleCtrlHandler 来做。

我们需要先定义一个 HandlerRoutine 的回调函数。

bool bQuit = false;
BOOL CALLBACK HandleCtrlEvent(DWORD dwCtrlType)
{
    switch (dwCtrlType)
    {
        case CTRL_C_EVENT: // 按下 Ctrl + C
        case CTRL_LOGOFF_EVENT: // 注销系统
        case CTRL_SHUTDOWN_EVENT: // 关闭系统
        case CTRL_CLOSE_EVENT: // 按下关闭按钮
        default:
            // do something to release
            bQuit = true;
            return false;
    }
	return TRUE;
}

这个回调函数会传入一个 DWORD 的值,表示其接收到的事件。具体定义可以参考 Microsoft 文档

这里判断了四个与程序关闭相关的事件,然后做对应是释放操作。这里我们操作一个 bool 变量,控制循环的退出。

int main()
{
    SetConsoleCtrlHandler(HandleCtrlEvent, TRUE);
    while(bQuit);
}

如果是 C# 程序,则可以通过 DllImport 导入,以及定义一个托管类型。

[DllImport("Kernel32")]
private static extern bool SetConsoleCtrlHandler(EventHandler HandlerRoutine, bool Add);

private delegate bool EventHandler(uint dwCtrlType);

然后就可以使用了:

class Program
{
    static EventHandler _handler;
    static bool _quit = false;

    private static bool Handler(uint sig)
    {
        switch (sig)
        {
            case 0:
            case 2:
            case 5:
            case 6:
            default:
                _quit = true;
                return false;
        }
    }

    static void Main(string[] args)
    {
        _handler += new EventHandler(Handler);
        SetConsoleCtrlHandler(_handler, true);
        while (!_quit);
    }
}