How to manage .Net's RCW COM object creation paramets (namely requested interface)? - com

I'm using an external native COM component in my C# .NET application.
This COM DLL doesn't have a type library, so I had to write the interop code myself, and having include/idl files I did it like TlbImp does.
But the worst thing is that the object creation fails with:
Creating an instance of the COM component with CLSID {40700425-0080-11D2-851F-00C04FC21759} from the IClassFactory failed due to the following error: 80040111
The class is finally created if I use the native CoCreateInstance and specify class_id and one of the implemented interface IIDs.
As it turned out the problem lies in that the COM object's IClassFactory::CreateInstance doesn't support IID_IUnknown passed as the riid parameter, and therefore returns CLASS_E_CLASSNOTAVAILABLE (I identified it with disassembler and debugger). The component is MS SQL VDI.
Is there any way to force the .NET RCW to pass a different interface ID into the CreateInstance method rather than IID_IUnknown?
I searched the net a lot, but didn't find a solution for this.
As a workaround I'm using C++/CLI now to create the object, requesting the proper interface instead of IID_IUnknown for this purpose now; but I would like to have code in C#, because C++/CLI requires me to build a different DLL for each platform.
Thanks

I repro. Brr, painful. You could pinvoke CoCreateInstance:
[return: MarshalAs(UnmanagedType.Interface)]
[DllImport("ole32.dll", ExactSpelling=true, PreserveSig=false)]
public static extern object CoCreateInstance(ref Guid clsid,
[MarshalAs(UnmanagedType.Interface)] object punkOuter, int context, ref Guid iid);

Related

Managed client implementing interfaces defined in managed COM object

I'd like to have a managed com object that exposes methods which accept as arguments objects implementing given interfaces. Something like this
[ComVisible(true)]
[Guid(".....")]
class SomeClass {
public void SomeMethod(ISomeInterface arg)
.....
Apparently ISomeInterface should also be declared ComVisible.
Now I want to consume that COM object in a managed client and call SomeMethod there. The problem is I need to instantiate an object that implements ISomeInterface. If that was a native COM object I'd get an interop assembly generated automatically and that won't be a problem. One cannot generate an interop assembly for managed COM object though.
I see that .NET 4.0 introduces the type equivalence concept. It looks like I could generate an interop manually using the ComImport attribute. But that looks like a pretty nasty job. I guess I could also use the TypeIdentifierAttribute but the documentation on that is vague and it says it's mostly intended for use by compilers.
So are there any other ways to do that?

.NET class as callback object in COM DLL

I am a relative newcomer to Windows programming and VB.net. What we are trying to do is call a function in an existing, 3rd party COM dll. This function requires a callback parameter, whose type is an interface also defined in the dll.
In our VB.net application, we have added the dll as a COM reference, and created a class that implements the interface in the DLL. We then send an object of that type as the callback parameter. This compiles fine. However, when we run the application, we receive an error stating that the program is unable to cast the object from our existing type to the interface type.
I suspect that there is a simple fix, but so far, my efforts to find a solution have come up short. If anyone could point me in the right direction, I'd be very grateful.
Thanks very much.
I suggest you to check whether the COM interface which you are implementing has a registerd proxy/stub or a correspondent typelibrary (tlb). You may check this by searching the interface's IID (this is a guid assossiated with this interface) in the registry:
Proxy/stub case:
HKEY_CLASSES_ROOT
Interface
{iid}
(Default) = ICustomInterfaceName
ProxyStubClsid32 = {clsid}
Typelibrary case:
HKEY_CLASSES_ROOT\TypeLib\{F37C8060-4AD5-101B-B826-00DD01103DE1}
HKEY_CLASSES_ROOT\TypeLib\{F37C8060-4AD5-101B-B826-00DD01103DE1}\2.0 = Automation Hello 2.0 Type Library.
HKEY_CLASSES_ROOT\TypeLib\{F37C8060-4AD5-101B-B826-00DD01103DE1}\2.0\HELPDIR =
; U.S. English.
HKEY_CLASSES_ROOT\TypeLib\{F37C8060-4AD5-101B-B826-00DD01103DE1}\2.0\9\win32 = hello.tlb
Replace {F37C8060-4AD5-101B-B826-00DD01103DE1} with a guid assossiated with your typelibrary.
In case if the typelibrary is registered. Check if its file is present on your PC

Cocreateinstance error

I have developed a COM dll in c++. Now I have a MFC client which uses some of the interfaces exposed by the COM dll. When calling CoCreateInstance from this application, it fails with the following error:80020008 DISP_E_BADVARTYPE. I have added a new interface and a new method in my idl file. I wish to pass structure for which I have defined the structure(with UUID) in the idl file. Now I am passing it as a SAFEARRAY in my method.Please help me understand this error and when does it occur.
DISP_E_BADVARTYPE is a COM interop marshalling error. (Is your client compiled with CLR support?) It means that a type can't be marshalled because it's not supported - it's not CLR-compliant, and perhaps not Automation-compatible either.
One cause of this problem is mismatched integer types, such as passing a CLR long integer to a COM dual interface (64-bit integers are not Automation-compatible.)
Another possible cause might be your structure type. SafeArrays of user-defined types are Automation-compatible (VT_ARRAY|VT_RECORD) and so I expect it's possible to do what you want to do. But maybe there's something incompatible in your UDT. Or maybe you've specified it incorrectly, like maybe VT_SAFEARRAY or VT_USERDEFINED.
Can you post your IDL?

COM Class Factories

i was looking for some COM, .NET interoperability topics, and i came across a few legacy COM examples using c++, to round it up, i understood that u define every interface and coclass inside and idl (interface definition file) so other com aware languages can understand type information, but the only com class not defined in an idl file is the one derived from IClassFactory, can some one please tell why since other .NET languages need also to obtain a class factory to instintiate other com classes, so how can they understand the type information ??
Class factories are rarely used directly. In fact, if you needed to create a class factory first to create any COM object, how would you create the class factory itself?
COM library takes care of creating objects. E.g., if COM server is a DLL, it is required to export DllGetClassObject function. When a client wants to create a COM object, it calls CoCreateInstance specifying a CLSID. Using CLSID, COM library finds the server and (if it's a DLL) loads it and calls its DllGetClassObject.
This is just a couple of words on the topic. COM is a very big topic; you might have to start at the very beginning if you want to have complete understanding...

queryinterface for interface failed

I'm using an interop COM assembly in my 1.1 VB.NET code, and when I try to set a property of a class, I get an InvalidCastException with the message "QueryInterface for Interface … failed."
Any ideas on this?
First, make sure your COM component is registered with regsvr32.exe.
Then, make sure any necessary marshalling support is also registered -- these come in one of two kinds:
1) proxy/stub DLL, usually called <YourComponent>ps.dll -- register this too with regsvr32.exe
2) Associated type library -- register this with regtlib.exe
If you used tlbimp on your DLL, try using regtlib to register the DLLs type library.