76

I am looking for a way to trigger a piece of code when a console application is manually closed (users closes window). Been trying with:

AppDomain.CurrentDomain.ProcessExit +=
    new EventHandler(CurrentDomain_ProcessExit);

but the above doesn't work if manually closed.

Is there any ways to use a .Net call for this or do I need to import the Kernel dll and do it that way?

Tim Sylvester
  • 22,897
  • 2
  • 80
  • 94
BlueVoodoo
  • 3,626
  • 5
  • 29
  • 37
  • 2
    Do you by "manually closing" mean that the user clicks on the "close window" cross in the upper right corner of the console window? – Martin Liversage Jan 10 '11 at 12:34
  • I suspect what you're after is the "On Exit" of the command line itself.. as soon the the `Main` method of the console application is done, it's out of your control and user need to press Enter key to close the command line window. – Shadow The GPT Wizard Jan 10 '11 at 12:45
  • @Martin. Yes, that's what I meant. Will update for clarification. – BlueVoodoo Jan 10 '11 at 12:55
  • @nawfal - The top answer in that one is wrong as I included in my snippet. – BlueVoodoo Jan 10 '14 at 11:39

2 Answers2

121

This code works to catch the user closing the console window:

using System;
using System.Runtime.InteropServices;

class Program {
    static void Main(string[] args) {
        handler = new ConsoleEventDelegate(ConsoleEventCallback);
        SetConsoleCtrlHandler(handler, true);
        Console.ReadLine();
    }

    static bool ConsoleEventCallback(int eventType) {
        if (eventType == 2) {
            Console.WriteLine("Console window closing, death imminent");
        }
        return false;
    }
    static ConsoleEventDelegate handler;   // Keeps it from getting garbage collected
    // Pinvoke
    private delegate bool ConsoleEventDelegate(int eventType);
    [DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool SetConsoleCtrlHandler(ConsoleEventDelegate callback, bool add);

}

Beware of the restrictions. You have to respond quickly to this notification, you've got 5 seconds to complete the task. Take longer and Windows will kill your code unceremoniously. And your method is called asynchronously on a worker thread, the state of the program is entirely unpredictable so locking is likely to be required. Do make absolutely sure that an abort cannot cause trouble. For example, when saving state into a file, do make sure you save to a temporary file first and use File.Replace().

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • That's very good to know. May have to work around that. Thanks for your reply. Upping your answer +1. – BlueVoodoo Jan 10 '11 at 13:19
  • 7
    Works great! If anyone's interested in the other possible event types: http://msdn.microsoft.com/en-us/library/ms683242%28v=vs.85%29.aspx – Ohad Schneider Jul 05 '11 at 08:44
  • saving to a temporary file first is a very good tip. it's not only safe against the application suddenly closing, but also the system. it's so simple. just what i was looking for +1 – symbiont Aug 28 '14 at 10:07
  • when assigning the delegate to the handler variable , you can also use a lambda expression instead.. – Legends May 05 '15 at 10:00
  • 1
    Using .NET 4.7.2 on Windows 10, works fine for me, did you misconfigure something? Or do I misunderstand your comment? – Codingale Oct 20 '19 at 22:25
28

You need to hook to console exit event and not your process.

http://geekswithblogs.net/mrnat/archive/2004/09/23/11594.aspx

Capture console exit C#

Community
  • 1
  • 1
Madhur Ahuja
  • 22,211
  • 14
  • 71
  • 124
  • 1
    The first Link from geekswithblogs isn´t working to 100% like you can read in the comments of the blog and the second link has also no answer for the win 7 problem – FoldFence Jan 17 '17 at 10:38