3
votes

I'm developing a Word Add-in using WPF windows. I'm using an UnhandledExceptionFilter to catch any unhandled exceptions so that Word doesn't throw an error message.

Dispatcher.CurrentDispatcher.UnhandledExceptionFilter += new DispatcherUnhandledExceptionFilterEventHandler(Dispatcher_UnhandledExceptionFilter);

void Dispatcher_UnhandledExceptionFilter(object sender, DispatcherUnhandledExceptionFilterEventArgs e)
{
  e.RequestCatch = false;
  // Display error message and close the window.
}

My event is fired correctly and I can display the appropriate error message box. However, for certain exceptions (e.g. null pointer exception in the window code), the exception is still being thrown to the calling class. While other exceptions (e.g. EndpointNotFoundException thrown from another helper class used in the window) is caught in my event and not rethrown.

Any thoughts? Thanks.

I asked an initial question about how to catch unhandled exceptions, but now I have this additional problem.

Catch C# WPF unhandled exception in Word Add-in before Microsoft displays error message

1
Did you resolve this? - rollsch
@rolls Nope. But I also haven't touched this in years. - Joe W
Posted my solution below for future reference for others. - rollsch

1 Answers

0
votes

I fixed this by using 3 different exception handlers as depending on how and where the exception is thrown you need to catch it separately. This also gives you the opportunity to cancel the termination and continue program execution based on your own decision of whether the exception is fatal or not.

using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
    
public class ExceptionHelper
{
    public static ExceptionHelper()
    {
        TaskScheduler.UnobservedTaskException += TaskSchedulerOnUnobservedTaskException;
        Application.Current.Dispatcher.UnhandledException += DispatcherOnUnhandledException;
        AppDomain.CurrentDomain.UnhandledException += CurrentDomainUnhandledException;
    }

    private static void TaskSchedulerOnUnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
    {
        e?.SetObserved();
        CurrentDomainUnhandledException(sender, new UnhandledExceptionEventArgs(e.Exception, false));
    }
    
    private static void DispatcherOnUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
    {
        e.Handled = true;
        CurrentDomainUnhandledException(sender, new UnhandledExceptionEventArgs(e.Exception, false));
    }
    
    public static void CurrentDomainUnhandledException(object sender, [CanBeNull] UnhandledExceptionEventArgs e)
    {
        //Program is hung, ensure we don't infinite loop on outofmemory exception by removing the handler
        var isTerminating = e?.IsTerminating == true;
    
        if (isTerminating)
        {
            TaskScheduler.UnobservedTaskException -= TaskSchedulerOnUnobservedTaskException;
            Application.Current.Dispatcher.UnhandledException -= DispatcherOnUnhandledException;
            AppDomain.CurrentDomain.UnhandledException -= CurrentDomainUnhandledException;
        }
    
        var ex = (Exception)e?.ExceptionObject;
        
        
        //Kill the app if we weren't already terminating and the program is in a corrupted state.

        if(!isTerminating)
            Process.GetCurrentProcess().Kill();
    
    }
}