none
Custom HRESULT marshalling RRS feed

  • Question

  • Hi,

    I have an existing COM component that on failure, passes meaningful HRESULTs which are defined in the non microsoft part of the HRESULT space.  I have written .Net exception classes which correspond to the HRESULTs.  When these failure HRESULTs are passed to .Net, they are not found in the HRESULT lookup table (of course) and coverted into COMExceptions. 

    What I would like to do is define a custom HRESULT marshaller...  instead of having the CLR create a COMException when the HRESULT is not found in the lookup table, runs some code of mine which will throw the correct exception.  I know that this was not possible in .Net 1.0 without wrapping every COM Interface with a .NET class which implements the same interface and catches the COMExceptions and throws the correct exception type.  Has this been added?  My application is nontrival, and creating wrappers would be far too time intensive and error prone.

    Thursday, January 29, 2009 11:02 PM

Answers

  • You ought to take a look at the managed Tlbimp.exe source code.  One of its features that fit your bill is the /PreserveSig argument.  That will still require a wrapper, but at least it is a trivial one.  Best of all, since it gives you the source code you could hack it to auto-generate the wrappers.

    Hans Passant.
    • Marked as answer by Zhi-Xin Ye Wednesday, February 4, 2009 10:33 AM
    Friday, January 30, 2009 12:56 AM
    Moderator

All replies

  • No, I don't believe the situation has changed since 1.0.

    Note that you can control the message that is generated if you are able to implement IErrorInfo in your COM component (SetErrorInfo API).  It will still be a COMException.

    > My application is nontrival, and creating wrappers would be far too time intensive and error prone.

    I suppose that you have considered providing a conversion routine and having your callers, upon catching COMException, call your conversion routine to determine the "strongly-typed" error.

    Thursday, January 29, 2009 11:50 PM
  • You ought to take a look at the managed Tlbimp.exe source code.  One of its features that fit your bill is the /PreserveSig argument.  That will still require a wrapper, but at least it is a trivial one.  Best of all, since it gives you the source code you could hack it to auto-generate the wrappers.

    Hans Passant.
    • Marked as answer by Zhi-Xin Ye Wednesday, February 4, 2009 10:33 AM
    Friday, January 30, 2009 12:56 AM
    Moderator
  • I suppose that you have considered providing a conversion routine and having your callers, upon catching COMException, call your conversion routine to determine the "strongly-typed" error.

     

    I have considered that, though unfortunately I am actually writing a software library which is to be used by people who do not know the nuances of my particular implementation, so I really do need to make sure the strongly typed errors are thrown with the user blissfully unaware. 

     

    Some of the library is written in .Net and some in native code, and all of it is COM exposed, though I wish to provide a "nicetylayer" (for lack of a better term) which makes the library feel like its all managed .Net to the .Net developer.  Otherwise it really is quite confusing to the user, the parts of the library written in .Net will throw the strongly typed error, so the user can catch the strongly typed error in that case, but the parts written in native throw COMExceptions, for what appears to be no good reason to the user.  With this use case, HRESULTs really do need to automatically show up as the correct exception type.  Other than the wrappers, the only thing I can think of is to forsake the COM spec and throw SEH exceptions directly from native code.
    • Edited by Nateman1352 Friday, January 30, 2009 1:22 AM
    Friday, January 30, 2009 1:04 AM
  • Hans - I was thinking of writing something using CodeDOM or Reflection.Emit to look at the .dll generated by tlbimp and generate wrappers for each interface definition, though I really like your idea of making my own custom tlbimp.exe that builds wrappers in to the interop .dll directly.

     

    Of course the wrapper thing would still actually be a little tricky, there are some functions that return IDispatch pointers which could possibly be an object that implements any one of my interfaces (and the object type changes depending on context at runtime as well), so I would need to QueryInterface() for each interface at runtime and figure out the correct wrapper class to use (if any.)  I'm not sure if you can reflect over a RCW and have it translate to QueryInterface calls underneath, but if all else fails I can just try casting to each interface type and catch the exception if it occurs (which will do terrible things to runtime perfomance of course, but better than nothing.)  At least nothing implements multiple interfaces *shiver*.

     

    Are you absolutely sure there is no way to modify the CLR's behavior (or heck, even the CLR itself?)


    Friday, January 30, 2009 1:19 AM
  • It doesn't sound like a actually took a look.  Your loss.
    Hans Passant.
    Friday, January 30, 2009 2:53 AM
    Moderator