【MAUI】在 .NET MAUI 中实现全局异常捕获的完整指南

文章目录

.NET MAUI 是 .NET 跨平台原生 UI 的未来,将成为 .NET的一部分... 在 .NET MAUI 开发中,全局异常捕获是提升应用稳定性的关键。以下基于 .NET MAUI 官方实践,提供完整实现方案:


一、核心方法

通过重写 Application 类方法实现跨平台异常捕获:

csharp 复制代码
// App.xaml.cs
public partial class App : Application
{
    public App()
    {
        InitializeComponent();
        MainPage = new MainPage();

        // 注册全局异常处理器
        AppDomain.CurrentDomain.UnhandledException += (sender, args) => 
        {
            var ex = (Exception)args.ExceptionObject;
            HandleException(ex);
        };
    }

    private void HandleException(Exception ex)
    {
        // 实现异常处理逻辑
        Console.WriteLine($"全局异常: {ex.Message}");
        // 可选:记录日志、通知用户或上报服务端
        #if DEBUG
            Application.Current?.MainPage?.DisplayAlert("错误", ex.Message, "确定");
        #endif
    }
}

二、平台适配技巧
  1. Android 特殊处理

    Platforms/Android/MainApplication.cs 添加:

    csharp 复制代码
    AndroidEnvironment.UnhandledExceptionRaiser += (sender, args) => 
    {
        Console.WriteLine($"Android 环境异常: {args.Exception}");
        args.Handled = true; // 阻止应用崩溃
    };
  2. iOS/macOS 优化

    通过 NSSetUncaughtExceptionHandler 捕获原生异常:

    csharp 复制代码
    #if IOS || MACCATALYST
    ObjCRuntime.Runtime.MarshalManagedException += (_, e) => 
    {
        Console.WriteLine($"Apple 平台异常: {e.Exception}");
        e.ExceptionMode = ObjCRuntime.MarshalManagedExceptionMode.Disable;
    };
    #endif
  3. Windows

csharp 复制代码
#elif WINDOWS

			// For WinUI 3:
			//
			// * Exceptions on background threads are caught by AppDomain.CurrentDomain.UnhandledException,
			//   not by Microsoft.UI.Xaml.Application.Current.UnhandledException
			//   See: https://github.com/microsoft/microsoft-ui-xaml/issues/5221
			//
			// * Exceptions caught by Microsoft.UI.Xaml.Application.Current.UnhandledException have details removed,
			//   but that can be worked around by saved by trapping first chance exceptions
			//   See: https://github.com/microsoft/microsoft-ui-xaml/issues/7160
			//
			Microsoft.UI.Xaml.Application.Current.UnhandledException += (sender, args) =>
			{
				var exception = args.Exception;

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

				UnhandledException?.Invoke(sender,"Microsoft.UI.Xaml.Application.Current.UnhandledException", new UnhandledExceptionEventArgs(exception, true));
			};
#endif

三、进阶实践
  1. 与日志系统集成

    结合 Microsoft.Extensions.Logging 记录异常:

    csharp 复制代码
    private void HandleException(Exception ex)
    {
        var logger = Handler.MauiContext.Services.GetService<ILogger<App>>();
        logger?.LogError(ex, "全局异常捕获");
    }
  2. 错误上报服务

    异步上报到后端:

    csharp 复制代码
    _ = Task.Run(async () => 
    {
        await MyErrorReportingService.ReportAsync(ex);
    });
  3. 用户友好提示

    在主线程显示弹窗:

    csharp 复制代码
    MainThread.BeginInvokeOnMainThread(() => 
    {
        MainPage?.DisplayAlert("系统错误", "已记录问题,请重试", "确定");
    });

四、注意事项
  1. 作用范围

    • OnUnhandledException:捕获 UI 线程异常
    • AppDomain.UnhandledException:捕获后台线程异常
    • 无法捕获原生崩溃(需平台特定工具)
  2. 调试模式差异

    DEBUG 环境下建议显示详细错误,RELEASE 下隐藏技术细节:

    csharp 复制代码
    #if RELEASE
    string message = "操作失败,请联系支持";
    #else
    string message = ex.ToString();
    #endif
  3. 性能影响

    避免在异常处理器中执行耗时操作,建议异步处理日志/上报逻辑。

参考官方路线图:.NET MAUI 在 .NET 7 中已正式支持全局异常处理机制。


相关问题

  1. 如何将 .NET MAUI 异常日志保存到本地文件?
  2. 在 Android/iOS 上捕获原生崩溃有哪些方案?
  3. .NET MAUI 的异常处理机制与 Xamarin.Forms 有何区别?