Open
Description
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;
}