Can you add a handler for WPF event exceptions? - c#

I have a single-threaded IronPython WPF application and if an event handler (FrameworkElement.SizeChanged for example) throws, the exception is just eaten and execution continues without any kind of notification.
Because of this I spent a lot of time today solving an "impossible" bug.
Does the same thing happen when using WPF from C#? What happens there if SizeChanged throws?
And is there a way to globally catch exceptions thrown by event handlers, but which don't terminate the application?

A useful trick in c# for catching exceptions globally, is to wrap the entry point for your program in a try-catch block. Any unhandled exceptions will wind their way up to it. Depending on the nature of the exception, it may stop the program from terminating.
EDIT
Thought this might also be relevant to your interests.
WPF global exception handler

Related

AppDomain.AssemblyLoad event catches all exceptions raised within the event handlers

It seems the .NET AppDomain.AssemblyLoad event catches any exceptions thrown within it's event handlers, not propagating them to the caller who triggered the assembly load (e.g. Assembly.LoadFile()).
My first question is why does this catch all exceptions behavior exist? Microsoft are generally pretty strict about ensuring exceptions always propagate in their BCLs.
My second question, is there any way to turn off this behavior?
Background: I need to scan assemblies as they are loaded and ensure they comply with some convention. If they don't, an exception should be thrown (and caught higher up by multiple mechanisms that could trigger the assembly load).
Note: I already found this question 'Throw exception from AppDomain.AssemblyLoad event', which is not a duplicate. My question logically follows from the conclusion of that question.
No, exceptions are swallowed inside the CLR, no way to alter that behavior. This is the case for most of the AppDomain events: AssemblyLoad, DomainUnload and ProcessExit. The SSCLI20 source code has no comments that indicate why this is done.
A rough guess is that the code is buried too deep inside CLR stack frames to allow a reasonable diagnostic and unwinding frames and restoring state is too difficult. AssemblyLoad because that event is almost always raised while the jitter is busy generating code, DomainUnload and ProcessExit because the CLR is busy shutting down all code execution.
The workaround is clear, if you must catch exceptions then you need a try/catch statement in your event handler.

Event Exception Handling In Framework

I'm looking for some guidance on best practices on handling exceptions in events. Currently, when exceptions are thrown in my application, the exception message is displayed in a pop up dialog and then the application restarts after hitting ok. The issue I'm seeing is that a lot of exceptions are occurring in the event handlers of some third party libraries and these exceptions are swallowed and never displayed since they are on a background thread. Here are a few solutions that various people have thought of and I would like to know of any of these are the best approach.
Forward the background thread to the UI thread in every event handler in the application.
Wrap the events in another class which has a try/catch around every method that invokes the event. The catch will then forward the exception to the UI thread if one occurs.
Get access to the third party libraries and put try/catch around where the events are being invoked, which could then be forwarded to the main application by a global event.
Lets discuss your options the way you listed them:
1) Forward the background thread to the UI thread in every event
handler in the application.
You should not and you can't! because:
You can't pretend if that event "which may comes from a third party" starts another background thread
or timer.
The whole point of having background threads is not
to freeze the UI, you will then struggle the user interface by a long execution codes.
2) Wrap the events in another class which has a try/catch around every method that invokes the event. The catch will then forward the exception to the UI thread if one occurs.
The same point as the previous. you can't pretend it that event starts another thread..
3) Get access to the third party libraries and put try/catch around where the events are being invoked, which could then be forwarded to the main application by a global event.
This is a bad choice, really, You should not change that code of third party libraries even if you can. because:
You are not the author for those libraries.
Whenever you want to update the library version or even change the libraries, you have to rewrite there code..
So what you have to do? The answer is some sort of what you are currently doing:
Whenever any exception thrown, log the exception restart your process, and at some point in your process send the logged bugs to your email and then start fixing them.
None of the above. Instead hook up the events on the Application and AppDomain for unhandled exceptions.
AppDomain.CurrentDomain.UnhandledException Event
Application.DispatcherUnhandledException Event
Further Information: The global exception handling event for WPF applications Application.DispatcherUnhandledException fires only for exceptions thrown on the main UI thread. However the AppDomain.CurrentDomain.UnhandledException should fire on any unhandled exception in any thread (unfortunately there is no preventing the application from shutting down after ward it reaches here).
Did some quick research on best practices and found that it is recommend that you manually handle exceptions on the background threads with try\catch block. Read the exception part on this page http://www.albahari.com/threading/ and also take a look at this StackOverflow question Catching unhandled exception on separate threads
If you're hooking the AppDomain.UnhandledException event, then the issue isn't the fact that they might be calling back on a background thread, but rather than the third-party library is explicitly swallowing exceptions thrown by the handlers. This is a badly behaving library, but, since you're writing the event handler code, you can catch the exceptions in the event handler and force the application to shut down.
Since the third-party library can't be stopped by throwing an exception, you can force the thread to terminate by calling:
Thread.CurrentThread.Abort();
Thread.Abort() is generally considered a bad practice, but it's slightly less dangerous here, as you are aborting yourself and therefore won't be injecting the exception into potentially nasty locations (you also know that the thread is not in an unmanaged context, so it will abort right away.) It's still a nasty hack, but the third-party application isn't giving you much choice. ThreadAbortException cannot be 'stopped', so the third-party code will terminate its thread as soon as it reaches the end of its exception handlers (even if they try to swallow it). If the third-party library is really nasty, it might invoke lots of code in its catch or finally blocks, even using dirty tricks to stay alive like launching other threads, but it would have to be pretty malicious to do this.
To get the friendly error message behavior, you can marshal the Exception to your UI thread using a SynchronizationContext or Dispatcher to call your exception-handler display (the easiest way may be to just re-throw the exception; I recommend embedding it as an InnerException so that you don't lose stack trace.)
If you really distrust the library (and don't want to give it the opportunity to stay alive even through its catch and finally blocks), you can explicitly marshal to the UI thread with a blocking invoke (to display your error message in a friendly way) and then call Environment.FailFast() to kill your process. This is a particularly harsh way to terminate (it will not call any cleanup code and literally tears down the process as quickly as possible), but it minimizes the possibility for any potentially damaging side effects if application state has become very corrupted. One possible thing to watch for here is that the UI thread could be blocked by some other UI invocation tied to the third-party code. If this happens, the application will deadlock. Again, this would be a pretty malicious thing for it to do, so you can probably ignore it.

Application.ThreadException vs AppDomain.UnhandledException

First some background: I have a multi-threaded WinForms application that is doing interop to native dlls. This application crashes sometimes with unhandled exception and we are trying to investigate why does it happen. In order to facilitate it, I am creating a global exception handler and I plan to generate process dumpfile from it.
Now coming towards question: as of now this application has handler for Application.ThreadException but it still crashes with unhandled exception. I am thinking of adding a handler for AppDomain.UnhandledException also although I am not sure if its going to help. Are there any possible unhandled exception in this scenario that will not be caught by Application.ThreadException?
Yes, Application.ThreadException can only trap exceptions that are raised in the UI thread. In code that's run due to Windows notifications. Or in technical terms, the events that are triggered by the message loop. Most any Winforms event fit this category.
What it does not trap are exceptions raised on any non-UI thread, like a worker thread started with Thread.Start(), ThreadPool.QueueUserWorkItem or a delegate's BeginInvoke() method. Any unhandled exception in those will terminate the app, AppDomain.UnhandledException is the last gasp.
Going further down-hill, hardware exceptions that are raised in an unmanaged thread by native code that never made any managed CLR call can not be detected with any CLR mechanism. An AccessViolation (exception code 0xc0000005) is the most common cause of death. The only way to trap those is through the Windows API, SetUnhandledExceptionFilter(). This is hard to get right.
You can disable Application.ThreadException with Application.SetUnhandledExceptionMode(). Which is a wise thing to do, giving the user the Continue option doesn't make a lot of sense. Now all exceptions in managed threads behave the same, use AppDomain.UnhandledException to log them.
Application.ThreadException will only be raised for unhandled exceptions on WinForms UI threads (see here.) Adding a handler for AppDomain.UnhandledException could help in this case (though with some caveats, as described in the remarks section here.)
I highly recommend that you use the OS minidump generation instead of your own. This is for several reasons:
Generating a minidump from within the same process is extremely problematic and not always possible.
By the time ThreadException or UnhandledException is started, the exception stack has already been unwound. Generating a minidump at that point will just point you to the handler, not the source of the exception.
If your app is in the field, use WER. If you're doing in-house testing, use ProcDump. You can also just copy the minidump file while the Error Reporting dialog is active.
P.S. There are some exceptional conditions - most notably when doing p/Invoke - where neither ThreadException nor UnhandledException will work.
P.P.S. If you have a debuggable scenario, then try turning on the Managed Debugging Assistants relating to p/Invoke.

Exception handling for events

I apologize if this is a simple question (my Google-Fu may be bad today).
Imagine this WinForms application, that has this type of design: Main application -> shows one dialog -> that 1st dialog can show another dialog. Both of the dialogs have OK/Cancel buttons (data entry).
I'm trying to figure out some type of global exception handling, along the lines of Application.ThreadException. What I mean is:
Each of the dialogs will have a few event handlers. The 2nd dialog may have:
private void ComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
AllSelectedIndexChangedCodeInThisFunction();
}
catch(Exception ex)
{
btnOK.enabled = false; // Bad things, let's not let them save
// log stuff, and other good things
}
}
Really, all the event handlers in this dialog should be handled in this way. It's an exceptional-case, so I just want to log all the pertinent information, show a message, and disable the okay button for that dialog.
But, I want to avoid a try/catch in each event handler (if I could). A draw-back of all these try/catch's is this:
private void someFunction()
{
// If an exception occurs in SelectedIndexChanged,
// it doesn't propagate to this function
combobox.selectedIndex = 3;
}
I don't believe that Application.ThreadException is a solution, because I don't want the exception to fall all the way-back to the 1st dialog and then the main app. I don't want to close the app down, I just want to log it, display a message, and let them cancel out of the dialog. They can decide what to do from there (maybe go somewhere else in the app).
Basically, a "global handler" in between the 1st dialog and the 2nd (and then, I suppose, another "global handler" in between the main app and the 1st dialog).
Yes, the default handling of Application.ThreadException was a mistake. Unfortunately, it was a necessary mistake, needed to not immediately discourage and despair hundreds of thousands of programmers writing their first Windows Forms application.
The fix you are contemplating is not a fix, it has a lot of potential to make it worse. While a user clicking the Continue button on the exception dialog is a questionable outcome, swallowing exceptions in a global exception handler is much worse.
Yes, do write a replacement handler for ThreadException. Have it display the value of e.Exception.ToString() in a message box so the user has some idea what blew up. Then fire off an email or append to an error log so you know what went wrong. Then call Environment.FailFast() so no more damage can be done.
Do the same for AppDomain.CurrentDomain.UnhandledException. It won't get much of a workout.
Use the feedback to improve your code. You'll find out where validation is required. You can help the customer's IT staff diagnose trouble with their LAN and equipment. And you'll find the very few cases where your own try/catch blocks might be able to recover from the exception.
You may be able to use the AppDomain.CurrentDomain.UnhandledException handler to intercept the errors on the main UI thread and handle them per-dialog. From MSDN:
In applications that use Windows
Forms, unhandled exceptions in the
main application thread cause the
Application.ThreadException event
to be raised. If this event is
handled, the default behavior is that
the unhandled exception does not
terminate the application, although
the application is left in an unknown
state. In that case, the
UnhandledException event is not
raised. This behavior can be changed
by using the application configuration
file, or by using the
Application.SetUnhandledExceptionMode
method to change the mode to
UnhandledExceptionMode.ThrowException
before the ThreadException event
handler is hooked up. This applies
only to the main application thread.
The UnhandledException event is raised
for unhandled exceptions thrown in
other threads.
You may like to rethink the design of your application slightly if you're doing stuff in combobox event handlers that might throw exceptions.
An alternative would be to initialise the dialog with all the information it needs before showing it to the user. The user then makes selections, and presses OK, and then the parent dialog could process the information in the dialog.
The exception handling could then be done in the parent dialog.
Of course this wouldn't be appropriate if you need to dynamically update the data in the dialog based on user actions...
e.g.
MyDialog myDialog = new MyDialog();
myDialog.Init(//data for the user to choose/manipulate);
if(myDialog.ShowDialog() == DialogResult.OK)
{
try{
ProcessDialogData(myDialog.SomeDataObject);
}
catch(/*...*/}
}
HTH
Global exception handling in WinForms application is done using two handlers: Application.ThreadException and AppDomain.CurrentDomain.UnhandledException. ThreadException catches unhandled exceptions in the main application thread, while CurrentDomain.UnhandledException catches unhandled exceptions in all other threads. Global exception handling may be used for the following purposes: showing user-friendly error message, logging the stack trace and other useful information, cleanup, sending error report to developer. After unhandled exception is catched, application should be terminated. You may want to restart it, but it is impossible to correct an error and continue, at least, in non-trivial applications.
Global exception handling is not replacement for local exception handling, which still should be used. Local exception handlers should never use catch Exception, because this effectively hides programming bugs. It is necessary to catch only expected exceptions in every case. Any unexpected exception should crash the program.
Sounds like you want aspects. PostSharp could help you out.

Unhandled Exception Handler in .NET 1.1

I'm maintaining a .NET 1.1 application and one of the things I've been tasked with is making sure the user doesn't see any unfriendly error notifications.
I've added handlers to Application.ThreadException and AppDomain.CurrentDomain.UnhandledException, which do get called. My problem is that the standard CLR error dialog is still displayed (before the exception handler is called).
Jeff talks about this problem on his blog here and here. But there's no solution. So what is the standard way in .NET 1.1 to handle uncaught exceptions and display a friendly dialog box?
Jeff's response was marked as the correct answer because the link he provided has the most complete information on how to do what's required.
Oh, in Windows Forms you definitely should be able to get it to work. The only thing you have to watch out for is things happening on different threads.
I have an old Code Project article here which should help:
User Friendly Exception Handling
Unhandled exception behavior in a .NET 1.x Windows Forms application depends on:
The type of thread that threw the exception
Whether it occurred during window message processing
Whether a debugger was attached to the process
The DbgJitDebugLaunchSetting registry setting
The jitDebugging flag in App.Config
Whether you overrode the Windows Forms exception handler
Whether you handled the CLR’s exception event
The phase of the moon
The default behavior of unhandled exceptions is:
If the exception occurs on the main thread when pumping window messages, it's intercepted by the Windows Forms exception handler.
If the exception occurs on the main thread when pumping window messages, it will terminate the app process unless it's intercepted by the Windows Forms exception handler.
If the exception occurs on a manual, thread-pool, or finalizer thread, it's swallowed by the CLR.
The points of contact for an unhandled exception are:
Windows Forms exception handler.
The JIT-debug registry switch DbgJitDebugLaunchSetting.
The CLR unhandled exception event.
The Windows Form built-in exception handling does the following by default:
Catches an unhandled exception when:
exception is on main thread and no debugger attached.
exception occurs during window message processing.
jitDebugging = false in App.Config.
Shows dialog to user and prevents app termination.
You can disable the latter behavior by setting jitDebugging = true in App.Config. But remember that this may be your last chance to stop app termination. So the next step to catch an unhandled exception is registering for event Application.ThreadException, e.g.:
Application.ThreadException += new
Threading.ThreadExceptionHandler(CatchFormsExceptions);
Note the registry setting DbgJitDebugLaunchSetting under HKEY_LOCAL_MACHINE\Software.NetFramework. This has one of three values of which I'm aware:
0: shows user dialog asking "debug or terminate".
1: lets exception through for CLR to deal with.
2: launches debugger specified in DbgManagedDebugger registry key.
In Visual Studio, go to menu Tools → Options → Debugging → JIT to set this key to 0 or 2. But a value of 1 is usually best on an end-user's machine. Note that this registry key is acted on before the CLR unhandled exception event.
This last event is your last chance to log an unhandled exception. It's triggered before your Finally blocks have executed. You can intercept this event as follows:
AppDomain.CurrentDomain.UnhandledException += new
System.UnhandledExceptionEventHandler(CatchClrExceptions);
AppDomain.UnhandledException is an event, not a global exception handler. This means, by the time it is raised, your application is already on its way down the drain, and there is nothing you can do about it, except for doing cleanup and error logging.
What happened behind the scenes is this: The framework detected the exception, walked up the call stack to the very top, found no handlers that would recover from the error, so was unable to determine if it was safe to continue execution. So, it started the shutdown sequence and fired up this event as a courtesy to you so you can pay your respects to your already-doomed process. This happens when an exception is left unhandled in the main thread.
There is no single-point solution to this kind of error. You need to put a real exception handler (a catch block) upstream of all places where this error occurs and forward it to (for example) a global handler method/class that will determine if it is safe to simply report and continue, based on exception type and/or content.
Edit: It is possible to disable (=hack) the error-reporting mechanism built into Windows so the mandatory "crash and burn" dialog does not get displayed when your app goes down. However, this becomes effective for all the applications in the system, not just your own.
Is this a console application or a Windows Forms application? If it's a .NET 1.1 console application this is, sadly, by design -- it's confirmed by an MSFT dev in the second blog post you referenced:
BTW, on my 1.1 machine the example from MSDN does have the expected output; it's just that the second line doesn't show up until after you've attached a debugger (or not). In v2 we've flipped things around so that the UnhandledException event fires before the debugger attaches, which seems to be what most people expect.
It sounds like .NET 2.0 does this better (thank goodness), but honestly, I never had time to go back and check.
It's a Windows Forms application. The exceptions that are caught by Application.ThreadException work fine, and I don't get the ugly .NET exception box (OK to terminate, Cancel to debug? who came up with that??).
I was getting some exceptions that weren't being caught by that and ended up going to the AppDomain.UnhandledException event that were causing problems. I think I've caught most of those exceptions, and I am displaying them in our nice error box now.
So I'll just have to hope there are not some other circumstances that would cause exceptions to not be caught by the Application.ThreadException handler.
The Short Answer,
Looks like, an exception occurring in Form.Load doesn't get routed to Application.ThreadException or AppDomain.CurrentDomain.UnhandledException without a debugger attached.
The More accurate Answer/Story
This is how I solved a similar problem. I can't say for sure how it does it, but here is what I think. Improvement suggestions are welcome.
The three events,
AppDomain.CurrentDomain.FirstChanceException
AppDomain.CurrentDomain.UnhandledException
and Application.ThreadException
accumulatively catch most of the exceptions but not on a global scope (as said earlier). In one of my applications, I used a combination of these to catch all kinds of exceptions and even the unmanaged code exceptions like DirectX exception (through SharpDX). All exceptions, whether they are caught or not, seem to be invoking FirstChanceException without a doubt.
AppDomain.CurrentDomain.FirstChanceException += MyFirstChanceExceptionHandler;
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); // not sure if this is important or not.
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; // can't use Lambda here. need to Unsub this event later.
Application.ThreadException += (s, e) => MyUnhandledExceptionHandler(e.Exception);
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
MyUnhandledExceptionHandler((Exception)e.ExceptionObject);
}
private void CurrentDomain_FirstChanceException(object sender, System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs eventArgs)
{
// detect the pattern of the exception which we won't be able to get in Fatal events.
if (eventArgs.Exception.Message.StartsWith("HRESULT"))
MyUnhandledExceptionHandler(eventArgs.Exception);
}
and the handler looks like
static void MyUnhandledExceptionHandler(Exception ex)
{
AppDomain.CurrentDomain.UnhandledException -= MyUnhandledExceptionHandler; // this is important. Any exception occuring in the logging mechanism can cause a stack overflow exception which triggers the window's own JIT message/App crash message if Win JIT is not available.
// LogTheException()
// Collect user data
// inform the user in a civil way to restart/close the app
Environment.Exit(0);
}
Unmanaged code exceptions like DirectX exceptions appeared only in FirstChanceException where I had to decide for myself if the exception was fatal or not. I then use MyUnhandledExceptionHandler to log and let the user know in a friendly way that everything was "under control".
IMPORTANT NOTE!
The scheme still didn't catch one kind of exception. It did appear in FirstChanceException, but it was hard to distinguish it from other kinds of exceptions hitting this handler. Any exception occurring directly in Form.Load had this different behavior. When the VS debugger was attached, these were routed to the UnhandledException event. But without a debugger, an old-school windows message will pop up, showing the stack trace of the exception that occurred. The most annoying thing was that it didn't let MyUnhandledExceptionHandlerr get kicked once it was done and the app continued to work in an abnormal state. The final solution I did was to move all the code from Form_load to another thread using MyForm.Load += (s,e) => new Thread(()=>{/* My Form_Load code*/ }).Start();. This way, Application.ThreadException gets triggered which is routed to MyUnhandledExceptionHandler, my safe exit.

Categories