Detecting console closing in .NET

 
 
  • Gérald Barré

In a console application I developed, I use FiddlerCore to intercept the HTTP requests of an application. FiddlerCore modifies the network settings of Windows. So, before closing the application, you must restore the original network settings. In .NET you can register the Ctrl+C and Ctrl+Break signals with Console.CancelKeyPress. This is the classic way of closing a console application. You can also close the console itself which will of course kill your application. However, the CancelKeyPress event doesn't handle the closing of the console window. Thus, the cleanup code won't run in this case.

Windows lets you register to the console events (Ctrl+C, Ctrl+Break and also the close event) using SetConsoleCtrlHandler. At the beginning of your code, you can call SetConsoleCtrlHandler, so you will be able to clean up your changes. Here's the complete code:

C#
class Program
{
    // https://learn.microsoft.com/en-us/windows/console/setconsolectrlhandler?WT.mc_id=DT-MVP-5003978
    [DllImport("Kernel32")]
    private static extern bool SetConsoleCtrlHandler(SetConsoleCtrlEventHandler handler, bool add);

    // https://learn.microsoft.com/en-us/windows/console/handlerroutine?WT.mc_id=DT-MVP-5003978
    private delegate bool SetConsoleCtrlEventHandler(CtrlType sig);

    private enum CtrlType
    {
        CTRL_C_EVENT = 0,
        CTRL_BREAK_EVENT = 1,
        CTRL_CLOSE_EVENT = 2,
        CTRL_LOGOFF_EVENT = 5,
        CTRL_SHUTDOWN_EVENT = 6
    }

    static void Main(string[] args)
    {
        // Register the handler
        SetConsoleCtrlHandler(Handler, true);

        // Wait for the event
        while (true)
        {
            Thread.Sleep(50);
        }
    }

    private static bool Handler(CtrlType signal)
    {
        switch (signal)
        {
            case CtrlType.CTRL_BREAK_EVENT:
            case CtrlType.CTRL_C_EVENT:
            case CtrlType.CTRL_LOGOFF_EVENT:
            case CtrlType.CTRL_SHUTDOWN_EVENT:
            case CtrlType.CTRL_CLOSE_EVENT:
                Console.WriteLine("Closing");
                // TODO Cleanup resources
                Environment.Exit(0);
                return false;

            default:
                return false;
        }
    }
}

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee💖 Sponsor on GitHub