Repository: microsoft/PowerToys
File: src/modules/cmdpal/Microsoft.CmdPal.UI/Helpers/GlobalErrorHandler.cs (C#)

Code before:
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using ManagedCommon;

using Microsoft.CmdPal.Common.Helpers;

using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.WindowsAndMessaging;

using SystemUnhandledExceptionEventArgs = System.UnhandledExceptionEventArgs;
using XamlUnhandledExceptionEventArgs = Microsoft.UI.Xaml.UnhandledExceptionEventArgs;

namespace Microsoft.CmdPal.UI.Helpers;

/// <summary>
/// Global error handler for Command Palette.
/// </summary>
internal sealed partial class GlobalErrorHandler
{
    // GlobalErrorHandler is designed to be self-contained; it can be registered and invoked before a service provider is available.
    internal void Register(App app)
    {
        ArgumentNullException.ThrowIfNull(app);

        app.UnhandledException += App_UnhandledException;
        TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    }

    private void App_UnhandledException(object sender, XamlUnhandledExceptionEventArgs e)
    {
        // Exceptions thrown on the main UI thread are handled here.
        if (e.Exception != null)
        {
            HandleException(e.Exception, Context.MainThreadException);
        }
    }

    private void CurrentDomain_UnhandledException(object sender, SystemUnhandledExceptionEventArgs e)
    {
        // Exceptions thrown on background threads are handled here.
        if (e.ExceptionObject is Exception ex)
        {
            HandleException(ex, Context.AppDomainUnhandledException);
        }
    }

    private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
    {

Review comment (bug):
@dhowett can I have you sanity check me here - this will catch all unhandled exceptions, sure. But it'll also prevent crashes from reaching the telemetry backend, right? 

Code after:
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using ManagedCommon;
using Microsoft.CmdPal.Core.Common.Helpers;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.UI.WindowsAndMessaging;
using SystemUnhandledExceptionEventArgs = System.UnhandledExceptionEventArgs;
using XamlUnhandledExceptionEventArgs = Microsoft.UI.Xaml.UnhandledExceptionEventArgs;

namespace Microsoft.CmdPal.UI.Helpers;

/// <summary>
/// Global error handler for Command Palette.
/// </summary>
internal sealed partial class GlobalErrorHandler
{
    // GlobalErrorHandler is designed to be self-contained; it can be registered and invoked before a service provider is available.
    internal void Register(App app)
    {
        ArgumentNullException.ThrowIfNull(app);

        app.UnhandledException += App_UnhandledException;
        TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    }

    private void App_UnhandledException(object sender, XamlUnhandledExceptionEventArgs e)
    {
        // Exceptions thrown on the main UI thread are handled here.
        if (e.Exception != null)
        {
            HandleException(e.Exception, Context.MainThreadException);
        }
    }

    private void CurrentDomain_UnhandledException(object sender, SystemUnhandledExceptionEventArgs e)
    {
        // Exceptions thrown on background threads are handled here.
        if (e.ExceptionObject is Exception ex)
        {
            HandleException(ex, Context.AppDomainUnhandledException);
        }
    }

    private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
    {
        // This event is raised only when a faulted Task is garbage-collected
        // without its exception being observed. It is NOT raised immediately
        // when the Task faults; timing depends on GC finalization.