Search code examples
.netdelphicom

.NET COM Interop -> Global exception handler


I have a .NET assembly which is invoked via COM Interop from a Delphi Host. I understand that any unhandled exception in the .NET code will be handled by the .net com interop framework and a correspoding HRESULT will be returned to the the COM host (delphi). Stack information is however lost during this Exception to HRESULT conversion.

The problem is that we would like to log all unhandled exceptions in .net code and I have not found any way to register a catch-all handler that is actually invoked whenever such an exception occurs.

I have tried:

  • AppDomain.CurrentDomain.UnhandledException
  • Dispatcher.CurrentDispatcher.UnhandledException

but these are not invoked when running under COM Interop.

Is it possible to define some sort of handler/callback for unhandled exceptions for the COM Interop Framework? Or somehow hook into the process of converting a Managed Exception to an HRESULT so that the exception can be logged?

Thanks!


Solution

  • I think the best option here would be to use something like

    void ComClassMethod()
    {
        try { ... } 
        catch (Exception ex) 
        { 
            /* store the ex in the object */; 
            throw; 
        } 
    }
    

    everywhere in your C# methods exposed to COM.

    Alternatively, you could handle AppDomain.CurrentDomain.FirstChanceException and store the last 1st-chance exception, which you could also expose to COM.

    However, pay special attention if your COM object support muliti-hreading (note, most .NET COM objects are free-threaded). In this case, you'd need to maintain a map between threads and their corresponding most-recent exceptions, either per object or globally via System.Threading.ThreadLocal<T> (decide what suits your logging requirements better).


    Updated, I've been thinking, there has to be a better way of doing this. And there is one, indeed, as explained here in Adam Nathan's excellent ".NET and COM: The Complete Interoperability Guide" book. I'm not sure I can copy/paste an exact quote from the copyrighted material, but the idea is the following:

    • All .NET CCW objects implement ISupportErrorInfo.
    • The extended error information - via an IErrorInfo object - can be retrieved on COM side via GetErrorInfo API.
    • According to Adam Nathan, this object also is the .NET exception object itself, and it implements the _Exception COM interface.
    • The COM client can use _Exception to get all the details, including _Exception.StackTrace.

    This seems to be exactly what you're looking for.