views:

1524

answers:

2

Our code library needs to be notified when the application is exiting. So we have subscribed to the System.Window.Forms.Application.ApplicationExit event. This works nicely for Winforms apps, but does it also work for other types of applications such as console apps, services, and web apps (such as ASP.NET)? The namespace would suggest that it doesn't, and it presumably gets raised when Application.Exit() is called (explicitly or implictly), which may not be correct to call for these other cases.

Is there some other event which would be better in these other cases or which would be more universal (great if it works for Winforms, too)? For example, is there an event for when Environment.Exit() is called (console app)?

I found a mention of an Exited event in System.Diagnostic.Process, but this appears to be for monitoring the exit of another process, and it does not appear to be received by a process about itself (for example, Process.GetCurrentProcess().Exited += Process_Exited; Process.GetCurrentProcess().EnableRaisingEvents = true;). I would think it might only be raised after the process has actually exited, so that wouldn't work.

This is particularly for .NET 2.0 and C#.

+1  A: 

This answer has the details for console apps. http://stackoverflow.com/questions/474679/capture-console-exit-c

Conor OG
Thanks for the link. I'm not sure if that will also handle the client code itself doing an exit of the console app, but it's at least a direction to experiment with when we get a chance to mock up a client console app.
Rob Parker
We like the looks of the AppDomain.CurrentDomain.DomainUnload event mentioned in one of the answers on that other question. It apparently allows the app domain to perform cleanup when exiting, which is exactly what we need, and it should work in all .NET environments including console and WPF.
Rob Parker
+3  A: 

We finally found more about this (but by then my machine had been rebuilt and lost the cookies to my unregistered profile here; hopefully, it will let met post this answer).

Further investigation eventually found a few more events which we have found helpful:

System.Windows.Forms.Application.ThreadExit - Fires when a message loop exits System.Windows.Forms.Application.ApplicationExit - Fires when all message loops exit System.AppDomain.CurrentDomain.DomainUnload - Fires when a domain other than the default exits System.AppDomain.CurrentDomain.ProcessExit - Fires when the default app domain exits System.AppDomain.CurrentDomain.UnhandledException - Fires when an uncaught exception occurs, ending the app.

Only one of the DomainUnload or ProcessExit events are possible for a given app domain, depending on whether it is the default (top-level) domain for the process or was created as a subdomain (eg. on a web server). If an application doesn't know which it might be (as in our case), it needs to subscribe to both if it wants to catch the actual unload for itself. Also, it appears that UnhandledException (which as of .NET2.0 is always fatal) may prevent the other two events, so that may be a third case to handle. These three events should work for any .NET application.

There is a caveat that the execution time for ProcessExit is bounded (about 4 seconds?), so it may not be possible to do extensive "final" work in that event handler. It needs to be something which can be done quickly.

The Application events only apply to WinForms applications (we suspect they may not apply in pure WPF applications, however). The naming can be misleading because they are named for their most basic normal usage which has certain assumptions. ThreadExit does not relate to the actual System.Threading.Thread but rather to the message loop (Application.Run())) of a UI thread, and ApplicationExit similarly relates to the collection of application Forms on one or more UI threads. Normally, once the call to Application.Run() returns, called from the entry method of a thread, the entry method quickly concludes and the thread itself then ends. And once all UI threads have exited, a WinForms app is usually all done and exits.

Another event of note is the System.Windows.Forms.Application.ThreadException event. A Windows message loop can be configured to catch exceptions which occur in handling a message and send this event rather than let them be uncaught (and thus fatal) exceptions. Catching these exceptions allows the message loop (and that UI thread) to continue running (after aborting the current message handler). There can be only one subscriber to this event at any time for a given thread (subscriptions overwrite any previous subscriber), and it must be configured before any Form is created and subscribed before entering the message loop. See the MSDN help for this event and System.Windows.Forms.Applicaton.SetUnhandledExceptionMode() for more info.

Rob Parker