1

The suggested duplicate is about DispatcherUnhandledException, not AppDomain.CurrentDomain.UnhandledException.

Original:

Where should AppDomain.UnhandledException be subscribed to? The example on MSDN just shows it in Main, which is what I do in Winforms: I subscribe to it in Program.Main :

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

But I can't find a suitable place for it in WPF where Main is hidden. I've searched, but mainly found discussions of whether to subscribe to it, assuming the reader would now where.

ispiro
  • 26,556
  • 38
  • 136
  • 291
  • You can do this in *app.xaml.cs*. See: [unhandled exception][1] [1]: http://stackoverflow.com/questions/2251868/unhandled-exception – musium May 19 '15 at 12:01
  • @musium That's only for `DispatcherUnhandledException`. At least intellisense doesn't show the same for `AppDomain.UnhandledException`. – ispiro May 19 '15 at 12:02
  • This is the nearest thing to UnhandledException (Winforms) in WPF. See: https://msdn.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception%28v=vs.110%29.aspx – musium May 19 '15 at 12:04
  • 1
    @musium No. It's not. See http://stackoverflow.com/a/1472562/939213 . – ispiro May 19 '15 at 12:06

3 Answers3

3

Assuming you created the project with the default template in Visual Studio, you should have a file named app.xaml and under it another file named app.xaml.cs.

Inside the App class you can add it at the beginning of OnStartup (along with the Dispatcher.UnhandledException):

protected override void OnStartup(StartupEventArgs e)
{
    // don't forget to call base implementation
    base.OnStartup(e);

    Dispatcher.UnhandledException += Dispatcher_UnhandledException;
    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}

Actually, Dispatcher.UnhandledException should be sufficient in most cases. Meaning you can skip using AppDomain.CurrentDomain.UnhandledException altogether. The only reason to also register to AppDomain.CurrentDomain.UnhandledException would be to get exceptions raised in threads other than the main UI thread. But I think that it is better practice to actually catch those exceptions in their respective thread.

Kryptos
  • 875
  • 8
  • 19
2

The Main() entrypoint in a WPF is auto-generated from the App.xaml source file. Earliest opportunity you have to subscribe the event is in the constructor for the App class in App.xaml.cs:

public partial class App : Application {
    public App() {
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    }

    private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
        // etc...
    }
}

This is however not "perfect", you cannot detect any failure in field initializers of your Application class. As well as any JIT compilation failures of types you use in your Application class, missing assemblies or versioning problems being the usual troublemakers.

To avoid missing those, you need to give up on the auto-generated code and write your own Main() method. With the assumption that you did not heavily modify the app.xaml file. Delete that file from the project and add a new class, I'd suggest Program.cs :) And make it look similar to this:

using System;
using System.Runtime.CompilerServices;
using System.Windows;

namespace WpfApplication1 {
    class Program {
        [STAThread]
        public static void Main(string[] args) {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            Start();
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        private static void Start() {
            var app = new App();
            app.Run(new MainWindow());
        }

        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
            // etc..
        }
    }

    public class App : Application {
        // etc..
    }
}
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
1

You can override the OnStartup method in your App.xaml.cs, which is the closest you get to the Main method (or use the App constructor` if you will)

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs e)
    {
        base.OnStartup(e);

        // register the event handler here
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    }
}

Note that this requires you to omit the StartupUri and open a Window yourself.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
  • 1
    Thanks. Is there a `base` OnStartup I'll have to call after that or is it usually empty? – ispiro May 19 '15 at 12:07
  • Yes, you should call it: http://referencesource.microsoft.com/#PresentationFramework/Framework/System/Windows/Application.cs,f2c567e5642bd030 – Patrick Hofman May 19 '15 at 12:08
  • @xanatos: Indeed. Removed it by accident from the sample code I copied. Even if it does nothing now I usually include it. – Patrick Hofman May 19 '15 at 12:09