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).