簡體   English   中英

絕對的COM混淆 - C#與早期綁定互操作

[英]Absolute COM Confusion - C# interop with early-binding

我一直在與VStudio,谷歌以及其他各種工具和網站進行斗爭,但沒有找到任何解決方案 - 幫助!

我有兩個COM接口(純COM,沒有ATL):

IMyClassFactory和IMyClass以及相應的實現

我想在沒有使用regsvr32注冊COM服務器的情況下從C#BUT使用它們。 我使用CoRegisterClassObject公開了Class Factory,並且我可以從非托管代碼中使用CoCreateInstance成功創建IMyClass的對象。

所以C#interop ...

我使用tlbimp myComServer.tlb創建了一個.NET包裝器,並將其作為對C#客戶端的引用加載。

然后,當我嘗試創建一個IMyClass實例時,我得到:

An unhandled exception of type 'System.InvalidCastException' occurred in COMTestClient.exe

Additional information: Unable to cast COM object of type 'MyComServerLib.MyClass' to interface type 'MyComServerLib.IMyClass'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{9F8CBFDC-8117-4B9F-9BDC-12D2E6A92A06}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)).

現在,我已經向QueryInterface添加了跟蹤,並且當我返回E_NOINTERFACE時,唯一的情況是它請求任何與Marshal相關的接口或IManagedObject。

我該如何解決??

編輯:我的IDL文件:

import "unknwn.idl";

[
    object, 
    uuid(...), 
    nonextensible,
    pointer_default(unique)
]
interface IMyClass : IUnknown
{
    HRESULT(SetFirstNumber)(long nX1);

    HRESULT(SetSecondNumber)(long nX2);

    HRESULT(DoTheAddition)([out,retval] long *pBuffer);
};

[
    uuid(...)
]
library MyLib
{
    importlib("stdole2.tlb");

    [
        uuid(...)
    ]
    coclass IMyClassImpl
    {
        [default] interface IMyClass;
    };
}

您需要允許對您的接口進行編組(即,在.idl文件中將其標記為不是“本地”,以便它最終在類型庫中,在代理/存根中),或者聚合自由線程marshaller如果你這樣走。

為了聚合FTM,我做了類似這樣的事情:

#define DECLARE_FTM() \
protected: CComPtr<IUnknown> _m_Marshal; \
DECLARE_GET_CONTROLLING_UNKNOWN() \
public: HRESULT FinalConstruct() \
{ return CoCreateFreeThreadedMarshaler(GetControllingUnknown(),&_m_Marshal); }

#define COM_INTERFACE_ENTRY_FTM() COM_INTERFACE_ENTRY_AGGREGATE(IID_IMarshal,_m_Marshal.p)

然后,在您的COM地圖中:

BEGIN_COM_MAP(Blah)
    COM_INTERFACE_ENTRY(IBlah)
    COM_INTERFACE_ENTRY_FTM()
END_COM_MAP()
DECLARE_FTM()

我注意到你沒有使用ATL之類的東西 - 你需要修改它,以便在查詢IMarshal時你的QueryInterface實現返回FTM指針。

請注意,聚合FTM並不是真正可以輕易完成的事情 - 它會產生一些並非總是有效的不安全假設。 例如,您的類不能使用任何本身不是自由線程的接口。

另一種選擇基本上就像@ [Franci Penov]所說,你需要確保你的界面能夠被編組。 我理解它的方式,有一個標准的marshaller能夠編組類型庫中的任何接口,或者你(也就是midl編譯器或多或少地自動執行)可以創建一個proxy / stub dll(或合並代碼)代理/存根到你自己的DLL),它能夠為你編組。

這篇文章更詳細地描述了構建和注冊代理/存根的過程

  1. 將您的界面移動到庫部分。 這將在類型庫中得到它的定義。
  2. 將您的界面標記為oleautomation。 這將標記為可以使用標准marshaller和typelib信息進行編組的接口,而不是midl編譯器生成的代理/存根。 (注意:雖然oleautomation確實來自舊的OLE世界,但它不需要您的接口從IDispatch派生)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM