bohdan_trotsenko
bohdan_trotsenko

Reputation: 5357

How to make a console app exit gracefully when it is closed

I wrote this little program to demonstrate the point of the question:

using System;
using System.IO;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        using (var disp = new MyDisp())
        {
            using (var ewhLocalExit = new EventWaitHandle(false, EventResetMode.ManualReset))
            {
                Console.WriteLine("Enter Ctrl+C to terminate the app.");
                Console.CancelKeyPress += (_, e) =>
                {
                    e.Cancel = true;
                    ewhLocalExit.Set();
                };
                ewhLocalExit.WaitOne();
            }
        }
        File.AppendAllText("Log.txt", "Terminated.\n");
    }
}


class MyDisp : IDisposable
{
    public MyDisp()
    {
        File.AppendAllText("Log.txt", "Started.\n");
    }

    public void Dispose()
    {
        File.AppendAllText("Log.txt", "Disposed.\n");
    }
}

When I run it and press Ctrl+C, I see "Started.Disposed.Terminated." in Log.txt
When I run it and close it with the mouse, I see only "Started."

How do I make exit gracefully, so that I at least could see "Disposed." ?

Upvotes: 7

Views: 2800

Answers (2)

Rui
Rui

Reputation: 4886

You can use DLLImport to import SetConsoleControlHandler and use it to register an event handler for the closed event (and others), here's an example snippet that shows it working (it will write closed in Log.txt whem you click the X to close the console):

class Program
{
    [DllImport("Kernel32")]
    public static extern bool SetConsoleCtrlHandler(HandlerRoutine Handler, bool Add);

    // A delegate type to be used as the handler routine 
    // for SetConsoleCtrlHandler.
    public delegate bool HandlerRoutine(CtrlTypes CtrlType);

    // An enumerated type for the control messages
    // sent to the handler routine.
    public enum CtrlTypes
    {
        CTRL_C_EVENT = 0,
        CTRL_BREAK_EVENT,
        CTRL_CLOSE_EVENT,
        CTRL_LOGOFF_EVENT = 5,
        CTRL_SHUTDOWN_EVENT
    }

    private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
    {
        if (ctrlType == CtrlTypes.CTRL_CLOSE_EVENT)
            File.AppendAllText(@"Log.txt", "closed");

        return true;
    }

    private static void Main(string[] args)
    {
        SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);
        Console.WriteLine("Close me");
        Console.ReadLine();
    }
}

Source

Upvotes: 4

Sean
Sean

Reputation: 62472

When you close your console app with the mouse by clicking the X button you are asking to have the process killed.

The Wi32 api has a SetConsoleControlHandler that allows you to specify a handler for when various things happen. If the handler is called with CTRL_CLOSE_EVENT then you know that someone is trying to kill your application.

There's an example of how to use this API here

Upvotes: 2

Related Questions