Reputation: 27633
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.
Upvotes: 1
Views: 966
Reputation: 941307
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..
}
}
Upvotes: 2
Reputation: 875
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.
Upvotes: 3
Reputation: 156938
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.
Upvotes: 1