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
Distinct by Property of Class with Linq
Is There a Way of Setting Culture for a Whole Application? All Current Threads and New Threads
C# - Faster Alternatives to Setpixel and Getpixel for Bitmaps for Windows Forms App
How to Let an Asmx File Output JSON
All Possible Combinations of a List of Values
How to Use Moq to Mock an Extension Method
Why Isn't There Generic Variance for Classes in C# 4.0
Deserialize JSON with Known and Unknown Fields
How to Determine the Owner of a Process in C#
How to Rethrow Innerexception Without Losing Stack Trace in C#
"The Controls Collection Cannot Be Modified Because the Control Contains Code Blocks"
Conditional Compilation and Framework Targets
Compiling/Executing a C# Source File in Command Prompt
Entity Framework Change Connection at Runtime