Globally Catch Exceptions in a Wpf Application

Globally catch exceptions in a WPF application?

Use the Application.DispatcherUnhandledException Event. See this question for a summary (see Drew Noakes' answer).

Be aware that there'll be still exceptions which preclude a successful resuming of your application, like after a stack overflow, exhausted memory, or lost network connectivity while you're trying to save to the database.

WPF catch all exceptions

As @Udontknow noted in his comment, not every exception has inner exception(s). Also, there can be, for instance, two inner exceptions. Thus, to correctly collect all exceptions, you can use the following helper GetAllExceptions extension method:

public static class ExtensionMethods
{
public static string GetAllExceptions(this Exception ex)
{
int x = 0;
string pattern = "EXCEPTION #{0}:\r\n{1}";
string message = String.Format(pattern, ++x, ex.Message);
Exception inner = ex.InnerException;
while (inner != null)
{
message += "\r\n============\r\n" + String.Format(pattern, ++x, inner.Message);
inner = inner.InnerException;
}
return message;
}
}

Example:

try
{
throw new Exception("Root Error", innerException: new Exception("Just inner exception"));
}
catch(Exception ex)
{
WriteLine(ex.GetAllExceptions());
}

Output:

EXCEPTION #1:
Root Error
============
EXCEPTION #2:
Just inner exception

WPF global exception handler

You can handle the AppDomain.UnhandledException event

EDIT: actually, this event is probably more adequate: Application.DispatcherUnhandledException

WPF MVVM Capture Global Exception Handler to Context

Why do you have to handle the exceptions in the apps code behind?

You can do that in your main window viewmodel. I am doing this and it is working fine.

if (Application.Current != null)
{
Application.Current.DispatcherUnhandledException += (s, a) =>
{
Reporter.AddLog(a.Exception);

DisplayAppropriateNotification(a);

a.Handled = true;
};
}

This is what I am doing in the constructor of my MainWindowViewmodel.

I guess you will have the context created in the viewmodel.

Global exception handling in MVVM

After a long battle finally I have found a very easily way to implement handling exceptions inside of ViewModel. While creating a BindingListener that inherits from DefaultTraceListener is certainly a great way to find your binding errors during the debug mode, this will not catch exceptions that have occurred inside a ViewModel when running solution is standard mode. But AppDomain.CurrentDomain.FirstChanceException will.

App.xaml.cs:

AppDomain.CurrentDomain.FirstChanceException += new EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs>(CurrentDomain_FirstChanceException);


private void CurrentDomain_FirstChanceException(object sender, FirstChanceExceptionEventArgs e)
{
Dispatcher.BeginInvoke(new Action(() => MessageBox.Show("Error Occurred \n\r" + e.Exception.Message + "\n\r" + e.Exception.StackTrace, "ERROR", MessageBoxButton.OK, MessageBoxImage.Error)));
}

WPF default behavior on exceptions

The docs seems to be wrong.

By default, a WPF application exits without any dialog box when an unhandled exception is thrown on the dispatcher thread.

You may consider to edit the docs and submit a PR on GitHub by clicking on the "Edit" button in the top right corner of the page.

WPF how to handle Exceptions and continue

Frankly, your entire design is a bad idea, in my opinion. It appears to me that you want to be able to "handle" these exceptions by logging them and letting your program continue executing. But that's an incredibly dangerous approach and definitely not recommended. You should only catch and handle exceptions for which you know in advance what the exception is and what the safe way to handle it is.

To do otherwise is to risk leaving your program in an unknown state, leading to anything from (at best) buggy behavior to (at worst) permanently corrupting the state of user's important data.

See also Should you catch all exceptions?

But, assuming you're going to do this anyway, you're not going to be able to use the LogUnhandledException() method to set the Handled property in the event args, because each of those events is different. Only the DispatcherUnhandledException event even has a Handled property to set. The UnobservedTaskException has an Observed property which you can set, and the AppDomain.UnhandledException event doesn't even have an analogous property.

However, you can of course specialize each handler to do that. For example:

protected override void OnStartup(StartupEventArgs e)
{
AppDomain.CurrentDomain.UnhandledException += (s, ex) =>
LogUnhandledException((Exception)ex.ExceptionObject,
"AppDomain.CurrentDomain.UnhandledException");

DispatcherUnhandledException += (s, ex) =>
{
LogUnhandledException(ex.Exception,
"Application.Current.DispatcherUnhandledException");
ex.Handled = true;
};

TaskScheduler.UnobservedTaskException += (s, ex) =>
{
LogUnhandledException(ex.Exception,
"TaskScheduler.UnobservedTaskException");
ex.SetObserved();
};
}

WPF global exception handler

You can handle the AppDomain.UnhandledException event

EDIT: actually, this event is probably more adequate: Application.DispatcherUnhandledException



Related Topics



Leave a reply



Submit