12

Is there a way to set up a global error handler for a MAUI app? My app is currently running fine when I launch it from Visual Studio. However on all simulators if I try and start the app up from the shell's app icon, it starts up then quits (and on iOS I get a crash dump). I have no idea where this is happening at, so wanted to try and catch in a global handler.

I looked at builder.ConfigureMauiHandlers, but it appears to only work with controls. You can't use a type of UnhandledExceptionEventHandler, which is what I was thinking would be appropriate.

I also tried an AppDomain handler, but it doesn't not appear to work either:

AppDomain ad = AppDomain.CurrentDomain;
ad.UnhandledException += Ad_UnhandledException;

Is this possible? I've only found samples for WCF and they don't work.

Steve Peschka
  • 1,015
  • 11
  • 25
  • try appcenter.ms - not sure if it supports MAUI, but it works with Xamarin Forms. – Jason Jun 01 '22 at 01:07
  • See if .net 6 or Xamarin Forms approach works. Either https://learn.microsoft.com/en-us/dotnet/api/system.appdomain.unhandledexception?view=net-6.0 or the older https://stackoverflow.com/a/39504448/199364. – ToolmakerSteve Jun 01 '22 at 01:09
  • Actually, the first link I gave looks like what you already tried. When you say it didn't work, what exactly do you mean? These CAN NOT stop a crash; they only give you a chance to log information. This is BY DESIGN (on Apple and Google's part); once one of those exceptions happen, its likely app is in an unreliable or corrupt state; continuing would risk data loss, and probably wouldn't work well anyway. – ToolmakerSteve Jun 01 '22 at 01:13
  • Might be informative to launch from VS via menu "Debug / Start without debugging". That should behave like launching from app icon, so it will likely crash. But if it doesn't, that would mean something (I'm not sure what yet). – ToolmakerSteve Jun 01 '22 at 01:17
  • Crashing when not under debugger (but no-crash when attached to debugger) is likely a **timing** issue. Some data you load for first screen is happening at a different time. It may be easier to get working (and to debug), to first load a simple screen. `MainPage = new LaunchPage();` While that page is showing, you load (access) any data you will need for your real main page. When data is ready, you set `MainPage = new AppShell();` or `MainPage = new MainPage();` - whatever is currently done in App.xaml.cs. – ToolmakerSteve Jun 01 '22 at 01:29
  • Okay, I finally figured out the crash part - but not how to do a global error handler. It took a ton of trial and error, but in short, I had an Entry control and in the Xaml markup I was assigning a style property for the TextColor property, like this: "{StaticResource FooStyle}". The problem is that it wasn't a color, it was a Style. When I changed the property to a color name I had in my Styles.xaml, it quit crashing on all platforms. So this was my fault, but seems like there should be some kind of compiler or run time check so it at least doesn't crash. – Steve Peschka Jun 01 '22 at 18:31
  • Most of my experience with .MAUI running fine in debug, but dumping after splash in release mode has been related to NUGET packages left over from Xamarin. Everything from SQLite to camera use components in some apps. I'd remove them, remark as needed, and see if you launch just fine... then investigate each component. Then try removing your renderers if still happening. During these "struggle sessions" I've experienced in past, rarely are the error messages / logging anything resembling informative. – Victor Thomas Wilcox Jr. Feb 21 '23 at 19:02

2 Answers2

2

There is a pretty lengthy github discussion here: https://github.com/dotnet/maui/discussions/653?sort=top#discussioncomment-3434251

The most popular response is from one of the Sentry developers, who offered a solution which uses first chance exception as show in this gist: https://gist.github.com/mattjohnsonpint/7b385b7a2da7059c4a16562bc5ddb3b7

The windows-specific implementation includes the following handlers, where _lastFirstChanceException is a private static variable.

    AppDomain.CurrentDomain.UnhandledException += (sender, args) => 
    {
        UnhandledException?.Invoke(sender, args);
    };

...

    AppDomain.CurrentDomain.FirstChanceException += (_, args) =>
    {
        _lastFirstChanceException = args.Exception;
    };

    Microsoft.UI.Xaml.Application.Current.UnhandledException += (sender, args) =>
    {
        var exception = args.Exception;

        if (exception.StackTrace is null)
        {
            exception = _lastFirstChanceException;
        }

        UnhandledException?.Invoke(sender, new UnhandledExceptionEventArgs(exception, true));
    };

While this worked for my use case, SonarLint did indicate that there were some issues with the static constructor approach. One solution to that would be to use a sealed MauiException class with a Lazy<MauiException> to access it as a threadsafe singleton, as Jon Skeet desccribes here: https://csharpindepth.com/Articles/Singleton

dperish
  • 1,493
  • 16
  • 27
1

Struggled with this for a while myself and ended up using Sentry.io, highly impressed so far!

Jimmy
  • 2,191
  • 6
  • 25
  • 45