Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use 32bit COM Server from a 64bit .NET Program

I'm having some trouble with COM Interop, the situation is as follows:

A 32-Bit COM Exe Server (that was programmed in C++) offers a class with some member functions that deal with 3rd party hardware (This hardware also ties the COM Exe Server to 32-Bit, since the manufacturer doesn't support 64-Bit).

I want to use the 32-Bit COM Exe Server in a 64-Bit .NET (C#) Application... At first I tried to add a reference to the Exe Server in Visual Studio 2010 and it created an Interop-DLL. This Interop-DLL provided me with the necessary functions, one of them being declared as:

int Initialize(ref string callingApplicationPath);

The original declaration in C++ looks like this:

LONG Class::Initialize(BSTR* callingApplicationPath)

...and like this in IDL:

[id(1)] LONG Initialize([in] BSTR* callingApplicationPath);

However, when I want to call this function from C# via the Interop-DLL, it throws a BadImageFormatException. Looks like the Interop-DLL is a 32-Bit DLL (Maybe there's a possibility to generate a 64-Bit-DLL?).

My next attempt was to instantiate the Exe Server with this code:

Type type = Type.GetTypeFromProgID("OurCompany.Class");
Object o = Activator.CreateInstance(type);
Object[] args = { Marshal.StringToBSTR(str) };
Object result = type.InvokeMember("Initialize", BindingFlags.InvokeMethod, null, o, args);

This code, on the other hand, throws a TargetInvocationException (More specifically: 0x80020005 (DISP_E_TYPEMISMATCH)) at my head. Unfortunately I was unable to find out what type I have to pass in to the function from C#... I tried all the StringToXXX-functions in the Marshal-class but nothing seems to work :/ I guess I'm missing something simple here, but I don't see what.

Any help is greatly appreciated!

Best Regards

Christian

like image 799
Christian Avatar asked Nov 05 '22 06:11

Christian


1 Answers

The IDL declaration

[id(1)] LONG Initialize([in] BSTR* str);    

makes no sense. When you pass a BSTR as an in parameter just pass it "by value":

[id(1)] LONG Initialize([in] BSTR str);

then you will not need to do anything special in C# code - just pass string there and marshalling will be done automatically.

Of course you'll have to change the method implementation signature as well.

like image 125
sharptooth Avatar answered Nov 10 '22 07:11

sharptooth