Using a COM dll from C# without a type library

前端 未结 7 2140
梦谈多话
梦谈多话 2020-12-14 12:23

I need to use a COM component (a dll) developed in Delphi ages ago. The problem is: the dll does not contain a type library... and every interop feature (eg. TlbImp) in .NET

相关标签:
7条回答
  • 2020-12-14 12:45

    You just need the CLS_ID and interface id. I wrote about this specific issue on my blog:

    "Using Obscure Windows COM APIs in .NET"

    0 讨论(0)
  • 2020-12-14 12:47

    I suspect that the dynamic keyword (C# 4.0) will accomplish this. If it does, it will give results which are largely equivalent to invoking the methods, i.e. how Groo suggests.

    0 讨论(0)
  • 2020-12-14 13:01

    You can also do late binding and then invoke methods through reflection (myObject.InvokeMember("NameOfTheMethod", options, params, etc.)).

    A wrapper should, however, offer better performance and faster marshalling.

    0 讨论(0)
  • 2020-12-14 13:04

    If you've managed to create an instance of the object, you're over the first major hurdle!

    Now try this:

    myObject.GetType().InvokeMember(
                          "ResObjOpen",  // method name goes here
                          BindingFlags.InvokeMethod,
                          null,
                          myObject,
                          new object[] { 
                             someClientID,   // arguments go here
                             someSubId, 
                             somFileName, 
                             someInt} );
    

    The reason I think you may need to do this is if the Delphi COM object is not a "dual" object. It may only support late binding, i.e. the kind of invocation you see above.

    (In C# 4.0 they're making this easier with the dynamic keyword.)

    EDIT: Just noticed something very suspicious. The IID for the interface and the CLSID for the object itself appear to be the same. That's not right.

    Given that you've succeeded in creating the object, it would appear to be the CLSID of the object. So it's not the right IID. You need to go back to your Delphi folks and ask them to tell you what the IID of the interface IResSrvDll is.

    Edit again: You could try changing the enum member you specify from ComInterfaceType. There should be ones for IDispatch and "dual" - although as your object doesn't support IDispatch, neither of those should be the right choice. The IUnknown setting (which appears in your sample code) should work - suggesting that the IID is wrong.

    0 讨论(0)
  • 2020-12-14 13:07

    It is quite frequent that you will encounter an interface implementation that is not backed by a type library (Delphi or otherwise). Shell extensions are one example.

    You basically need to make a Windows API call to create the instance through the proper COM function calls. The API will take care of managing the DLL via the exported functions you mentioned earlier.

    You will need to recreate the interface definition in C# code but after that you simply create the object, cast it to the interface, and it is no different than anything else. The only real caveat here is, depending on your usage, you may have some threading issues to deal with so check the "threading model" that was used for the DLL and consider your usage based on that.

    Here is a link to a tutorial on consuming the interfaces that are not TLB based. Tutorial

    0 讨论(0)
  • 2020-12-14 13:07

    Yes and no.

    All C# (and any CLR language) needs in order communicate with a COM object is a compatible interface signature. Typically specifying the methods, GUID and apartment style of the interface. If you can add this definition into your code base then the TLB is not necessary.

    There is a small caveat that comes with that statement. I believe you will get into trouble if you try and use a COM object across apartment boundaries and don't have a suitable TLB registered. I can't 100% remember on this point though.

    0 讨论(0)
提交回复
热议问题