Run code on console close?
Asked Answered
C

3

15

I am writing a C# app that needs to upload a file when the console is closed (be it via the X button, or the computer is shut down).

How could I do this?

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

Only runs when I issue the exit command to the console, not when I hit the red close button.

Please only answer if the solution runs both when the console is closed via the X button, and when the computer is shut down (normally via Windows, I know you can't if the power is pulled xD).

Carpology answered 27/3, 2012 at 20:32 Comment(5)
sorry do say but there are scenarios where your process is killed so you cannot get this to work in every possible case (maybe you've seen it on Win7 where you hit shutdown and the system tells you that some processes prevent shutdown and you can choose to terminate them)Distributary
@CarstenKönig I understand there are situations like that, but I want it to at least work under a normal shutdown process in the event that the user doesn't force close the apps.Carpology
possible duplicate https://mcmap.net/q/109836/-capture-console-exit-cLorentz
@lazyberezovsky The person who answered that question said it doesn't work on Win7.Carpology
@ ryansworld10 that's why you selected copy of that answer as correct answer?Lorentz
K
14

You have to invoke the WIN32 API, to do this, just have a look at this post here http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/707e9ae1-a53f-4918-8ac4-62a1eddb3c4a/

I copied the relevant code for you from there:

class Program

{
    private static bool isclosing = false;

    static void Main(string[] args)
    {
        SetConsoleCtrlHandler(new HandlerRoutine(ConsoleCtrlCheck), true);

        Console.WriteLine("CTRL+C,CTRL+BREAK or suppress the application to exit");

        while (!isclosing) ;
    }

    private static bool ConsoleCtrlCheck(CtrlTypes ctrlType)
    {
        // Put your own handler here

        switch (ctrlType)
        {
            case CtrlTypes.CTRL_CLOSE_EVENT:
                isclosing = true;
                Console.WriteLine("Program being closed!");
                break;
        }

        return true;
    }

    #region unmanaged
    // Declare the SetConsoleCtrlHandler function
    // as external and receiving a delegate.

    [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
    }

    #endregion
}

It does exactly what you need.

Greetings,

Kellogg answered 27/3, 2012 at 20:39 Comment(1)
What does the returning bool do in the HandlerRoutine delegate?Counterproductive
H
1

I'll also like to suggest you should save what you want to upload for later so you don't have broken/invalid files uploaded. That way next time the application is started, the upload can be performed. This one at least works for System Logoff/Shutdowns:

SystemEvents.SessionEnding += (SystemEvents_SessionEnding);

private static void SystemEvents_SessionEnding(object sender, SessionEndingEventArgs e)
{
    //code to run on when user is about to logoff or shutdown
}
Hemato answered 27/3, 2012 at 20:49 Comment(0)
S
0

May be something like this (assuming that I right understood you request)

//get all command windows in the system
Process[] processes = Process.GetProcessesByName("cmd");


// find that one you interested in 
Process mypro;

Subscribe to Process.Exited event of it like

mypro.Exited += (s,e) =>
{
   //here upload the file
}

Should work for you.

Spelldown answered 27/3, 2012 at 20:38 Comment(2)
I think, you never should do it like that! because what if there are more than one single processes called "cmd". If you wanna subscribe to the process, please add some filtering to the code, e.h. the name of the Process-Window and not the Process itself.Rosenthal
@MarioFraiß: sure. Infact the story about how that cmd process located was skipped in my post. You need kind of "strong key" in order to be able to find the cmd.exe was requested.Spelldown

© 2022 - 2024 — McMap. All rights reserved.