C# and COM Interop and HRESULTs  
Author Message
Tuckers





PostPosted: Visual C# Language, C# and COM Interop and HRESULTs Top

Hi,

I have a COM object that I am using via c#. THe object supports a method
that checks an angle lower and upper limits and returns a bool. The
result is either a pass or fail, if it fails further information is
passed via the HRESULT indicating whether it failed the upper limit or
lower limit check. So this is not an error just a logical failure. Is
there anyway I can look at the contents of the HRESULT after the call,
even when an exception is not thrown

Thanks

Tuckers




Visual C#6  
 
 
Andres Alos





PostPosted: Visual C# Language, C# and COM Interop and HRESULTs Top

Hi,

try to override the default behavoiur of platform Invoke by setting the DllImportAttribute.PreserveSig to false.

Something like this:


using System.Runtime.InteropServices;
public class Win32 {
    [DllImport("user32.dll", PreserveSig=false)]
    public static extern int MessageBoxA(int hWnd, String text, String
       caption, uint type);

Regards,

Andres.

 
 
Mattias Sjogren





PostPosted: Visual C# Language, C# and COM Interop and HRESULTs Top

Andres is sort of on the right track, except that you're using COM interop and not P/Invoke. What you have to do is to apply the PreserveSig attribute to the method where you want to explicitly handle the returned HRESULT. This is easy if you manually declare the interface but nontrivial (requires modifying the interop assembly) if you get the definition from an interop assembly generated by TlbImp of VS.



 
 
Tuckers





PostPosted: Visual C# Language, C# and COM Interop and HRESULTs Top

Thanks Mattias,

This sounds more trouble than its worth.

Regards

Tuckers

 
 
Bernhard Kirchner





PostPosted: Visual C# Language, C# and COM Interop and HRESULTs Top

Hello Sjorgen,

I am highly interested in the solution you would propose for this issue - because I am having the same issue on multiple methods of an unmanaged, C++ written COM-Server: The HRESULT return value in many cases is either S_OK, or S_FALSE, or some "serious" error condition. The "serious" errors arrive in my managed C# module as exceptions - fine. But how can I distinguish between S_OK and S_FALSE (S_FALSE does not trigger any exception on the C# side, which provides void methods all over the place)

Already read about the PreserveSigAttribute - but how could I apply it to the affected methods For me a solution, that requires modification of the original IDL-File (provided by the unmanaged, C++ written COM-Dll) would be acceptable and welcome. For example I could apply whatever MIDL attributes to these methods - just I would like to avoid changing their signature for backwards compatibility reasons.

So how can I apply the PreserveSigAttribute BEFORE I import the COM-Dll into my C# program

Many thanks in advance,

Best regards
Bernhard


 
 
Mattias Sjogren





PostPosted: Visual C# Language, C# and COM Interop and HRESULTs Top

There's no IDL attribute that will help you here but you can edit the interop assembly. See http://msdn.microsoft.com/library/en-us/cpguide/html/cpconeditinginteropassembly.asp frame=true#cpconeditingmicrosoftintermediatelanguagemsilanchor5 for details.



 
 
Jonathan Freidin





PostPosted: Visual C# Language, C# and COM Interop and HRESULTs Top

If you only need the HRESULT, you can extract it from the exception that is thrown:

catch (System.Runtime.InteropServices.COMException exception)
{
    // textBoxHresult.Text = exception.Message;
    textBoxHresult.Text = String.Format("HRESULT = 0x{0:X}", exception.ErrorCode);
}

Output parameters won't be available unless you customize the Runtime Callable Wrapper (RCW). See http://msdn2.microsoft.com/en-us/library/e753eftz.aspx
Of these two methods, the first (use tlbimp.exe to generate the RCW, ildasm.exe to dissassemble it into MSIL, edit to add PreserveSig and then ilasm.exe to assemble) is easier, but the second (writing the RCW in C# code) seems more supportable in a development process.

A somewhat terse example of a C# RCW may be found here:
    http://msdn2.microsoft.com/en-us/library/x8fbsf00.aspx
Learning to do this is pretty hard, but http://www.microsoft.com/belux/msdn/nl/community/tools.mspx
includes a link to Reflector for .NET (http://www.aisto.com/Roeder/DotNet/), a tool for decompiling the RCW into C#, which may be modified to include [PreserveSig].

If someone has a better way, please post it.