Managed exceptions in MAUI Windows app logged as CoreMessagingXP.dll crashes
See the question and my original answer on StackOverflowMAUI on Windows is implemented using WinUI3. WinUI3 itself is a native framework that has bindings/projections for .NET (but also C++), etc.
Anyway in Windows, unless something catches it, a crash will end up in the Event Log. This is the case by default with WinUI3 and MAUI over it, and that's what you see (note that with proper setup and symbols, a developer can investigate that kind of raw reports).
Here is how you can catch it (I've use the System.Diagnostics.EventLog package but you can use any logging facility):
Change Platforms\Windows\App.xaml.cs
like this:
public partial class App : MauiWinUIApplication
{
public App()
{
// we handle only our specific exception type in case of
// unobserved exceptions, best effort for bad coding practises :-)
AppDomain.CurrentDomain.FirstChanceException +=
(sender, e) => HandleException(e.Exception as MyException);
UnhandledException += (sender, e) =>
{
// prevent the app from crashing & exit gracefully
e.Handled = true;
HandleException(e.Exception);
};
InitializeComponent();
}
private void HandleException(Exception? ex)
{
if (ex == null) return;
// pick a source that exists like "Application" or create a new one (requires admin rights)
// here we use ".NET Runtime"
// see why here https://www.jitbit.com/alexblog/266-writing-to-an-event-log-from-net-without-the-description-for-event-id-nonsense/
System.Diagnostics.EventLog.WriteEntry(
".NET Runtime",
$"Unhandled exception: {ex.Message}",
System.Diagnostics.EventLogEntryType.Error,
1000);
Exit();
}
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();
}
This is the result in Event Viewer:
Now, why the first line? Because your reproducing code does this:
private async void OnLanguageClicked(object? sender, EventArgs e)
{
throw new Exception("Simulated exception in OnLanguageClicked");
}
Note with Visual Studio the green swiggles:
What it means is the implicit task you're starting with the async
keyword is unobserved. It's generally bad practise, and in this case it crashes the native layers underneath (which could handle this in a better way we agree on that...) so you get a real native handled error that you can see in the event viewer.
In this case there are two ways of dealing with this kind of errors:
A: use a custom exception type for all your errors and you can catch it in FirstChanceException handler (there are many other 1st chance exceptions that we don't care about that's why you need a custom one), so for example this would be caught by our handlers:
private async void OnCounterClicked(object? sender, EventArgs e)
{
throw new MyException("hello from main page");
}
public class MyException : Exception
{
public MyException(string message) : base(message) { }
}
B: (preferred as it works for types of exceptions), just make sure you don't use this type of void async
bad practise code and use this pattern instead:
private void OnCounterClicked(object? sender, EventArgs e)
{
_ = DoSomethingThatThrows();
}
Task DoSomethingThatThrows()
{
throw new Exception("hello from main page");
}