How to implement an application crash reporter in a WPF application


When using (modern) software applications you most likely have encountered occasional crashes. When crashing, some applications just get closed but many programs show some kind of error reporting dialog after they have crashed. Mozilla’s Firefox for example will show the following (or a similar) dialog if it encounters a problem and crashes: Mozilla Firefox Crash Reporter

Having a crash reporter for your application has a number of advantages:

  • You can inform your users first-hand what happened and if their data has been saved
  • You may allow your users to send some diagnostic data which help you in fixing the cause of the crash (opt-in)
  • You can provide some recovery options to your users (save the currently opened files etc.)
  • You can provide an option to directly restart the application which reduces friction

But what do you have to do if you want to implement such a reporter in one of your WPF applications? Most application crashes (at least the ones you can handle, as opposed to your program being killed by the task manager for example) are due to an exception which occurs somewhere (in your main thread) and is not handled on its way up the stack. Windows will then terminate your application and shows its own error reporting dialog similar to the one in the following screenshot.

Default windows crash reporter dialog

Consequently, the first step when implementing a crash reporter is to catch these unhandled exceptions by registering a handler for unhandled exceptions in your application class (i.e. in App.xaml.cs).

protected override void OnStartup(StartupEventArgs e)
{
    Application.Current.DispatcherUnhandledException += CrashHandler;

    base.OnStartup(e);
}

protected void CrashHandler(object sender, DispatcherUnhandledExceptionEventArgs e)
{
	// TODO: log the error

	// show the custom crash reporter dialog
	CrashInfoWindow f = new CrashInfoWindow(e.Exception);
    f.ShowDialog();

	// signal that you handled the exception -> application will not be terminated automatically
	e.Handled = true;
}

In this handler you can then open a custom dialog which shows information about the exception which was previously unhandled. If possible, you should only use functions from the .Net standard libraries in your crash handler, since depending on the cause of the exception, some application parts may be unstable or will not work as expected. This is especially true for third-party libraries or MVVM frameworks such as Caliburn.Micro or Prism. Consequently, you should create the crash reporter dialog without using functions from these frameworks. If an exception occurs in your crash handler your application will be terminated right away.

In the dialog you should inform the user what happened (the reason they are seeing this window) and present diagnostic information about the error (i.e. the stacktrace). Of course, you can collect other data about the current execution state of your application as well (be aware that some data might be sensitive to the user so try to collect only data you require to diagnose the crash and inform the user about what information they will send to you).

Custom crash reporter dialog

Furthermore, you should present your users possible options to recover from the crash, e.g. Continue, Restart, Exit. The easiest way to restart a .Net application is by importing the System.Windows.Forms assembly which allows you to write System.Windows.Forms.Application.Restart(); before terminating it.

As you indicate in the global exception handler that you handled the exception, it is possible for your application to continue execution. However, depending on the cause of the exception your application might be unstable or may not react as expected.

As usual, if you just want to close the application call Application.Current.Shutdown([errorCode]);.