views:

285

answers:

2

I have a Windows Forms application that has this code in the program's start up:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.Automatic);

In the MSDN Documentation for UnhandledExceptionMode.Automatic it states that:

Automatic - Route all exceptions to the ThreadException handler, unless the application's configuration file specifies otherwise.

Does anyone know exactly which element/attribute in the config file it is that affects this setting?

A: 

Maybe this is the answer to your question? Handling "Unhandled Exceptions" in .NET 2.0

Jakob Christensen
This article refers to <legacyUnhandledExceptionPolicy enabled="1" /> I don't think this is it as this setting only seems to affect whether AppDomain.CurrentDomain.UnhandledException gets called. It does not seem to affect Application.ThreadException as Application.SetUnhandledExceptionMode does.
Martin Brown
+1  A: 

I wondered about this as well, and I was never able to find anything about any specific built-in config option you could set (there may be one, but I never found a mention of what it was). I think we also found that the default behavior (if you do none of this) is equivalent to ThrowException mode, contrary to what MSDN implies in that quote. Also, I believe that setting it to Automatic is equivalent to not touching it at all; it's already in Automatic to start with.

However, I did discover that there are two overloads of SetUnhandledExceptionMode. The normal one operates on a per-thread basis (usually you only have one UI thread, anyway), but the second one also takes a boolean which determines whether the setting is applied only to the current thread (true) or to all UI threads (false). Passing false acts like setting a default setting for future UI threads if they are left set in Automatic mode when they start (by which I mean message loops, ie. calls to Application.Run), and you can hook your own configuration option into making this call to set your global default. I have to wonder if that's what they were really getting at with the vague "config" reference.

The caveat though, is that calling SetUnhandledExceptionMode must be done before creating any window handle in the same context. So calling it with false must be done before creating any window handle on any thread. Also, the Visual Studio debugger apparently causes a window handle to exist before your code starts, so this call can never succeed (with false) when debugging. However, that window handle is not on your thread, so the normal call (or with true) can be safely done in a debugging scenario. I'm not sure how this behaves in other cases where the WinForms app is in a created subdomain rather than as the top/initial domain, whether a subdomain inherits the any-handle-created flag or gets to start fresh. Perhaps that's the actual problem in the Visual Studio case.

The normal call (or with true) still has to be made before creating any window handle on that thread. I believe this setting will persist through the exit of the application context if you then reenter Application.Run on the same thread (as does the handle-created flag which breaks further calls to change it). But be aware that the subscription to Application.ThreadException is on a per-thread, per-context basis and will be lost when Application.Run exits. It also can have only a single subscriber (overwrites any previous subscriber), and can't be changed while the message loop is running. So if you are calling Application.Run again you must resubscribe to Application.ThreadException before calling Application.Run, or they will instead be caught and sent to the default WinForms handler (I don't mean UnhandledException) because the "exception mode" setting persists. Normally, you don't keep entering and exiting a message loop on the same thread, so that isn't an issue, but we ran into it because we had to do that in the Gibraltar.Agent.

AppDomain.UnhandledException, however, is a normal event with multiple subscribers and is not thread-specific. Subscribe to it once and you're covered for the entire AppDomain (eg. CurrentDomain).

Rob Parker
Thanks for adding the link, Martin. It took me a couple moments to figure out what you'd altered because the edit history doesn't highlight the change in metadata. And now I see how to do links here; I would not have figured that out by trial and error! Unfortunately, we're both still waiting for a definitive answer on your specific question.
Rob Parker