Class DefaultErrorHandler
The default unexpected exception handler for WPF applications.
public class DefaultErrorHandler : IErrorHandler
- Inheritance
-
DefaultErrorHandler
- Implements
- Inherited Members
Examples
Application initialization could look like this:
internal sealed partial class App : Application
{
private static readonly DefaultErrorHandler s_errorHandler = new DefaultErrorHandler();
// Since we're providing our own Main method, add the following to the project file:
// <EnableDefaultApplicationDefinition>false</EnableDefaultApplicationDefinition>
[STAThread]
public static void Main()
{
try
{
// Set the error handler logger as soon as possible,
// creating it for whatever framework is being used and using an adapter as needed.
// This should be within the try/catch, in case an exception is thrown while initializing logging.
// For example, an adapter could be used to adapt ILogger to log4net:
s_errorHandler.Logger = new Log4NetLoggerAdapter(s_errorHandler.GetType().FullName);
s_errorHandler.ApplicationName = Properties.Resources.AppName;
// Continue with application initialization and startup:
var app = new App();
// As soon as we have our Application object, wire up the event handlers:
s_errorHandler.SetUpUnhandledExceptionHandling(app);
app.InitializeComponent();
app.Run();
}
catch (Exception ex)
{
s_errorHandler.HandleUnexpectedException(ex);
}
}
}
Remarks
See the remarks for HandleUnexpectedException(Exception) for details about how unexpected errors are handled.
To handle all possible unexpected exceptions in a WPF application, first, initialize error handling:
- Define a static instance of this class, created via a static initializer.
- Define a custom Main method with an outer try-catch statement with a handler for Exception that calls HandleUnexpectedException(Exception).
- As soon as possible, set the Logger property to a logger. Do this within the outer try-catch loop so an exception thrown while initializing the logger will be handled.
- Set the ApplicationName property.
- As soon as possible after the Application instance is created, call SetUpUnhandledExceptionHandling(Application).
Then, within the rest of the application code:
- If there are any other possible places where unexpected exceptions could occur without triggering normal error handling (e.g., Prism navigation failure events, handled via Microsoft.Practices.Prism.Regions.IRegionNavigationService.NavigationFailed), call HandleUnexpectedException(Exception).
- Make sure that all async/await code follows best practices for Task-based asynchronous programming patterns, so that exceptions are properly handled. In particular, use HandleFaultAsUnexpectedException(Task, IErrorHandler) on any "fire-and-forget" tasks to immediately handle unhandled exceptions (even though SetUpUnhandledExceptionHandling(Application) will set up a handler for unobserved task exceptions which will eventually be triggered by the task finalizer). In other words, watch out for any calls to asynchronous methods that do nothing with the returned Task object.
If another unexpected error occurs while displaying the message box for the first one, the details will be logged, but no message box will be shown.
Constructors
DefaultErrorHandler()
Initializes a new instance of the DefaultErrorHandler class.
public DefaultErrorHandler()
Properties
ApplicationName
Gets or sets the application name, which is used as the caption of and within text in the message box that displays unexpected error messages.
public string ApplicationName { get; set; }
Property Value
Remarks
If this is not set, "the application" will be used as the application name, and "Unexpected Error" will be used for the message box caption, each localized to the UI thread culture language, if possible.
ErrorInstructions
Gets or sets the error instructions that will be shown in the message box that displays unexpected error messages. This can be set to null for no instructions to be shown.
public string ErrorInstructions { get; set; }
Property Value
Remarks
This defaults to "Please contact your system administrator for assistance.", localized to the UI thread culture language, if possible.
Logger
Gets or sets the logger to use to log errors. If this is null (which is the default), error details will not be logged, and the exception message will be included in the error message box.
[CLSCompliant(false)]
public ILogger Logger { get; set; }
Property Value
Methods
HandleUnexpectedException(Exception)
Handles an unexpected exception.
public void HandleUnexpectedException(Exception exception)
Parameters
exception
ExceptionThe unexpected exception.
Remarks
This handles unexpected errors by doing the following:
- Log the error details via Logger (if it is not null), as a critical error with an "An unhandled exception occurred" message.
- Display an error message via a message box. (If error details were not logged in the previous step, the error message will be included.) Note that while the error message box is being shown, application code can continue to run, both via the main dispatcher/Windows message loop and in background threads. Generally, log entries after the initial "An unhandled exception occurred" entry should be ignored.
- Exit the application with a process exit code of 1.
Because this shows a message box, care must be taken about what thread it is called from. It is best to call it from the main UI thread. It should definitely not be called from the object finalizer thread.
SetUpUnhandledExceptionHandling(Application)
Sets up handlers for unhandled application exceptions.
public void SetUpUnhandledExceptionHandling(Application application)
Parameters
application
ApplicationThe Application for which to set up exception handlers.
Remarks
Handlers are added to handle unexpected errors from these sources:
- The application dispatcher.
- The current application domain (to handle exceptions from non-UI threads).
- Unobserved task exceptions.
Note that handlers are not set up when running in debug mode with a debugger attached, as it is assumed that when an unhandled exception occurs, the debugger will break into the program at the point of the exception, allowing it to be debugged before closing down the program (except for unobserved task exceptions, which are always handled since they won't crash the application, breaking inside the debugger, even with an attached debugger).
Exceptions
- ArgumentNullException
application
is null.- InvalidOperationException
Handlers have already been set up by calling this method before.