c# - WPF global exception handler

ID : 7940

viewed : 174

Tags : c#.netwpfexceptionexception-handlingc#





Top 5 Answer for c# - WPF global exception handler

vote vote

90

You can trap unhandled exceptions at different levels:

  1. AppDomain.CurrentDomain.UnhandledException From all threads in the AppDomain.
  2. Dispatcher.UnhandledException From a single specific UI dispatcher thread.
  3. Application.Current.DispatcherUnhandledException From the main UI dispatcher thread in your WPF application.
  4. TaskScheduler.UnobservedTaskException from within each AppDomain that uses a task scheduler for asynchronous operations.

You should consider what level you need to trap unhandled exceptions at.

Deciding between #2 and #3 depends upon whether you're using more than one WPF thread. This is quite an exotic situation and if you're unsure whether you are or not, then it's most likely that you're not.

vote vote

86

You can handle the AppDomain.UnhandledException event

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

vote vote

73

A quick example of code for Application.Dispatcher.UnhandledException:

public App() {     this.Dispatcher.UnhandledException += OnDispatcherUnhandledException; }  void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) {     string errorMessage = string.Format("An unhandled exception occurred: {0}", e.Exception.Message);     MessageBox.Show(errorMessage, "Error", MessageBoxButton.OK, MessageBoxImage.Error);     // OR whatever you want like logging etc. MessageBox it's just example     // for quick debugging etc.     e.Handled = true; } 

I added this code in App.xaml.cs

vote vote

61

I use the following code in my WPF apps to show a "Sorry for the inconvenience" dialog box whenever an unhandled exception occurs. It shows the exception message, and asks user whether they want to close the app or ignore the exception and continue (the latter case is convenient when a non-fatal exceptions occur and user can still normally continue to use the app).

In App.xaml add the Startup event handler:

<Application .... Startup="Application_Startup"> 

In App.xaml.cs code add Startup event handler function that will register the global application event handler:

using System.Windows.Threading;  private void Application_Startup(object sender, StartupEventArgs e) {     // Global exception handling       Application.Current.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(AppDispatcherUnhandledException);     }  void AppDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) {         \#if DEBUG   // In debug mode do not custom-handle the exception, let Visual Studio handle it      e.Handled = false;      \#else      ShowUnhandledException(e);          \#endif      }  void ShowUnhandledException(DispatcherUnhandledExceptionEventArgs e) {     e.Handled = true;      string errorMessage = string.Format("An application error occurred.\nPlease check whether your data is correct and repeat the action. If this error occurs again there seems to be a more serious malfunction in the application, and you better close it.\n\nError: {0}\n\nDo you want to continue?\n(if you click Yes you will continue with your work, if you click No the application will close)",      e.Exception.Message + (e.Exception.InnerException != null ? "\n" +      e.Exception.InnerException.Message : null));      if (MessageBox.Show(errorMessage, "Application Error", MessageBoxButton.YesNoCancel, MessageBoxImage.Error) == MessageBoxResult.No)   {         if (MessageBox.Show("WARNING: The application will close. Any changes will not be saved!\nDo you really want to close it?", "Close the application!", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning) == MessageBoxResult.Yes)     {         Application.Current.Shutdown();     }  } 
vote vote

56

Best answer is probably https://stackoverflow.com/a/1472562/601990.

Here is some code that shows how to use it:

App.xaml.cs

public sealed partial class App {     protected override void OnStartup(StartupEventArgs e)     {         // setting up the Dependency Injection container         var resolver = ResolverFactory.Get();          // getting the ILogger or ILog interface         var logger = resolver.Resolve<ILogger>();         RegisterGlobalExceptionHandling(logger);          // Bootstrapping Dependency Injection          // injects ViewModel into MainWindow.xaml         // remember to remove the StartupUri attribute in App.xaml         var mainWindow = resolver.Resolve<Pages.MainWindow>();         mainWindow.Show();     }      private void RegisterGlobalExceptionHandling(ILogger log)     {         // this is the line you really want          AppDomain.CurrentDomain.UnhandledException +=              (sender, args) => CurrentDomainOnUnhandledException(args, log);          // optional: hooking up some more handlers         // remember that you need to hook up additional handlers when          // logging from other dispatchers, shedulers, or applications          Application.Dispatcher.UnhandledException +=              (sender, args) => DispatcherOnUnhandledException(args, log);          Application.Current.DispatcherUnhandledException +=             (sender, args) => CurrentOnDispatcherUnhandledException(args, log);          TaskScheduler.UnobservedTaskException +=              (sender, args) => TaskSchedulerOnUnobservedTaskException(args, log);     }      private static void TaskSchedulerOnUnobservedTaskException(UnobservedTaskExceptionEventArgs args, ILogger log)     {         log.Error(args.Exception, args.Exception.Message);         args.SetObserved();     }      private static void CurrentOnDispatcherUnhandledException(DispatcherUnhandledExceptionEventArgs args, ILogger log)     {         log.Error(args.Exception, args.Exception.Message);         // args.Handled = true;     }      private static void DispatcherOnUnhandledException(DispatcherUnhandledExceptionEventArgs args, ILogger log)     {         log.Error(args.Exception, args.Exception.Message);         // args.Handled = true;     }      private static void CurrentDomainOnUnhandledException(UnhandledExceptionEventArgs args, ILogger log)     {         var exception = args.ExceptionObject as Exception;         var terminatingMessage = args.IsTerminating ? " The application is terminating." : string.Empty;         var exceptionMessage = exception?.Message ?? "An unmanaged exception occured.";         var message = string.Concat(exceptionMessage, terminatingMessage);         log.Error(exception, message);     } } 

Top 3 video Explaining c# - WPF global exception handler







Related QUESTION?