Get a COM object to throw an exception for any result except S_OK (0) in C #

I am currently working on updating a project that makes extensive use of COM / MFC / (who knows how many other technologies). As part of the update, we are trying to transfer as much functionality as we can to managed C # code, but, unfortunately, some things just can’t move (for reasons I won’t go into it). One of these things is a section of code that grossly violates COM and returns pointers to HRESULT, which are then passed to other objects that implement the COM interface. I tried the following code to convert HRESULT to a pointer, which I can then get from the interface:

MyComInterfaceInCS myObj = null; try { world.GetTD_MyComInterfaceInCS(); } catch (COMException comException) { int pointerValue = Marshal.GetHRForException(comException); IntPtr myObjPointer = new IntPtr(pointerValue); myObj = (MyComInterfaceInCS) Marshal.GetObjectForIUnknown(myObjPointer); } 

.... but, a COM exception is thrown, and I assume this because the pointer is not a negative value and, therefore, is technically not a COM error. Is there a way to configure COM on an object to throw a COM exception on something? BUT S_OK (0)?

+5
source share
1 answer

Two thoughts:

  • Find and kill (or severely cripple) whoever implements this library
  • Implementing a wrapper in managed C ++ since you will need to call the HResult method directly, and I cannot figure out how to do this using interop.

EDIT

Another option is to declare COM interfaces in C #, so the signature of each method returns HRESULT and uses [out retval] for the returned values. This will allow you to retrieve and examine HRESULT of all method calls, not just those that throw a COMException.

By default, COM interop typeimport "captures" the method signatures so that the HRESULT return is deleted on the managed side, and the interop layer throws exceptions for E_FAIL, etc., essentially throwing S_OK, S_FALSE, etc.

There are some explanations in this article , and the PreserveSig attriubte documentation has some additional details.

This will most likely require you to declare all COM interfaces manually instead of using tlbimp , but you can get tlbimp to save the signature of the COM methods.

This will allow you to stay purely in C #, but in your shoes I would go with managed C ++, since it is easier to interact with COM in this non-standard mode.

+5
source

All Articles