Making a Windows Forms App Respond to System Shutdown
Normally when Windows is shutting down, every top level window gets asked to close, and once they’re all closed, the system can shut down. Some applications, however, don’t exit when you close their main window - they hide the main window and leave a NotifyIcon icon on the system tray. When you double-click on the tray icon, the main window is made visible again.
This is how MSN Messenger works, for example, and many other applications.
The problem here is that when Windows wants to shut down, it sends you the close message, but it looks exactly the same as when the Close button is clicked by the user. You hide your window, you don’t quit, and the system doesn’t shut down.
To get around this, you need to detect a system shutdown event specifically.
There’s a message that you get sent when the system is shutting down, WM_QUERYENDSESSION. As much as I hate using native Win32 functions or message handling in a Windows Forms app, there doesn’t appear to be any other way to catch a system shutdown event than to use this.
I tried registering a notificaiton with SystemEvents.SessionEnding, which should have done the job, but if your main window is hidden, you don’t receive it.
So here’s what I ended up using:
// // Watch for WM_QUERYENDSESSION, set the // reallyQuit flag and quit // protected override void WndProc(ref Message m) { base.WndProc(ref m); // WM_QUERYENDSESSION if (m.Msg == 0×11) { reallyQuit = true; Close(); }; }
And then only allow the Closing event if reallyQuit is set. This seems to get the job done.