Skip to content

Feature request: Exception callbacks #1571

Open
@hez2010

Description

@hez2010

Proposal: Exception callbacks

Summary

In out-of-proc scenario, we can only see COMException without any message from the client if any unhandled exception happens on the server (see #1562).
We cannot intercept it without wrapping every API with a try-catch block. This makes it difficult to do unified unhandled exception handling and logging.
I propose to add the support for exception callbacks which allows propagate the exception to a user specified handler to handle unhandled exceptions:

namespace WinRT;

public static class ExceptionHelpers
{
        /// <summary>
        /// Unhandled WinRT server exception event.
        /// </summary>
        public static event EventHandler<UnhandledWinRTServerExceptionEventArgs> UnhandledWinRTServerException;

        public class UnhandledWinRTServerExceptionEventArgs : EventArgs
        {
            public Exception Exception { get; }
            public bool Handled { get; set; }

            public UnhandledWinRTServerExceptionEventArgs(Exception exception)
            {
                Exception = exception;
            }
        }

        public static bool TryHandleWinRTServerException(object sender, Exception ex)
        {
            EventHandler<UnhandledWinRTServerExceptionEventArgs> handler = UnhandledWinRTServerException;
            if (handler != null)
            {
                UnhandledWinRTServerExceptionEventArgs args = new UnhandledWinRTServerExceptionEventArgs(ex);
                handler.Invoke(sender, args);
                return args.Handled;
            }
        }
}

WinRT codegen

[UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvStdcall) })]
private static unsafe int Do_Abi_GetPoint_2(IntPtr thisPtr, global::Windows.Foundation.Point* __return_value__)
{
    global::AuthoringTest.BasicClass __this__ = default;
    global::Windows.Foundation.Point ____return_value__ = default;
    *__return_value__ = default;
    try
    {
        ____return_value__ = (__this__ = global::WinRT.ComWrappersSupport.FindObject<global::AuthoringTest.BasicClass>(thisPtr)).GetPoint();
        *__return_value__ = ____return_value__;

    }
    catch (Exception __exception__)
    {
        if (global::WinRT.ExceptionHelpers.TryHandleWinRTServerException(__this__, __exception__))
        {
            return 0;
        }
        global::WinRT.ExceptionHelpers.SetErrorInfo(__exception__);
        return global::WinRT.ExceptionHelpers.GetHRForException(__exception__);
    }
    return 0;
}

Usage

WinRT.ExceptionHelpers.UnhandledWinRTServerException += (sender, args) =>
{
    // ...
    if (this_exception_has_been_handled_correctly) args.Handled = true;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions