简体   繁体   中英

C# Execute code before application exits for background app

This is not a duplicate of this post . I got my solution from this post but it does not work not to mention my app is a winforms app, not a console app.

So I have a project that is running in the background. Basically, I created a Windows forms application but I am not calling the Form in Program.cs. I created a class that listens to when the application exits:

class ShutDownManager
    {
        public ShutDownManager()
        {
            _handler += new EventHandler(Handler);
            SetConsoleCtrlHandler(_handler, true);
        }
        static bool exitSystem = false;


        [DllImport("Kernel32")]
        private static extern bool SetConsoleCtrlHandler(EventHandler handler, bool add);

        private delegate bool EventHandler(CtrlType sig);
        static EventHandler _handler;

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

        private static bool Handler(CtrlType sig)
        {
            Console.Writeline("I'M OUT OF HERE");


            return true;
        }

    }

I create an instance of this class in Program.cs's Main function. However this does not seem to fire. It works like a charm in Console applications but when it comes to my forms application (without the form) it doesn't work. What could be the problem?

My code in Main:

static void Main()
{
     ShutDownManager sdm = new ShutDownManager();
     StartUpManager.AddApplicationToCurrentUserStartup();
     Timers timers = new Timers();
}

Let me break down your situation: An excerpt from docs.microsoft.com on SetConsoleCtrlHandler

Each console process has its own list of application-defined HandlerRoutine functions that handle CTRL+C and CTRL+BREAK signals. The handler functions also handle signals generated by the system when the user closes the console, logs off, or shuts down the system. A console process adds or removes additional handler functions by calling the SetConsoleCtrlHandler function, which does not affect the list of handler functions for other processes.

As you notice, this seems to be referring to Console process only. And it cannot tell you when other application exit, but only about this application. In addition it can notify you of LOGOFF and SHUTDOWN . Also, since there is no console (as you want a background process), there is no CTRL-C or CTRL-BREAK processing involved.
Conclusion : the best case is that you can only be notified about LOGOFF and SHUTDOWN

Relevant information from the same page for winforms app:

This function provides a similar notification for console application and services that WM_QUERYENDSESSION provides for graphical applications with a message pump.

What is the problem with your code?

Well, it is designed to provide a callback when the system has LOGOFF or SHUTDOWN when the application is running . Needless to say, your application has already exited to receive such events. So you have to wait after registering your callback.

What is the best way to do it?

You should write a service for this. And if I am not mistaken, service already gets a notification for LOGOFF and SHUTDOWN How to write a simple C# service has a good example.

EDIT:

For more comprehensive understanding , you might want to look at the MSDN docs about ServiceBase class . Also, you should look at the OnSessionChange event, which is notified about all session events . It has some useful code excerpt at SessionChangeDescription class doc . Similarly for OnShutdown event

Now if you can't do windows service, you will have to create a Form from your winform application and make the Form invisible. You should then handle the WM_QUERYENDSESSION event or use the SystemEvents.SessionEnding Event to handle the situation

Sample code for that

var frm = new Form();
frm.Activated += (s, e) => { frm.Visible = false; };
SystemEvents.SessionEnded += (s, e) => { /* your code to handle logoff and shutdown */ };
Application.Run(frm);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM