2008-11-11 73 views
2

我需要使一段C#代碼通過COM與各種實現進行交互。在C#中爲客戶端和服務器使用C++ COM接口

爲了讓該集成的用戶更輕鬆,我將交互的接口包含在IDL中(作爲相關現有DLL的一部分,但沒有coclass或實現),然後通過運行Tlbimp創建類型定義。

我實現了我的C#,基於Windows註冊表信息創建COM對象,並將對象轉換爲我需要的接口。

然後我在一個單獨的項目中創建了接口的C#實現並註冊它。 主程序正確創建了測試COM對象,但未能將其轉換爲接口(使用C#'獲取空對象作爲',獲取顯式強制轉換的InvalidCastException)。

有人可以建議爲什麼接口不被識別爲由測試對象實現嗎?

這是在IDL接口defition(編譯的C++中VS 2005):

[ 
    object, 
    uuid(B60C546F-EE91-48a2-A352-CFC36E613CB7), 
    dual, 
    nonextensible, 
    helpstring("IScriptGenerator Interface"), 
    pointer_default(unique) 
] 
interface IScriptGenerator : IDispatch{ 

    [helpstring("Init the Script generator")] 
     HRESULT Init(); 
    [helpstring("General purpose error reporting")] 
     HRESULT GetLastError([out] BSTR *Error); 
}; 

這是通過TLBIMP爲C#創建的存根:

[TypeLibType(4288)] 
[Guid("B60C546F-EE91-48A2-A352-CFC36E613CB7")] 
    public interface IScriptGenerator 
    { 
    [DispId(1610743813)] 
    void GetLastError(out string Error); 
    [DispId(1610743808)] 
    void Init(); 
    } 

這是主要的部C#代碼,創建它的進程id一個COM對象,並將其投射到IScriptGenerator接口:

public ScriptGenerator(string GUID) 
{ 
    Type comType = Type.GetTypeFromProgID(GUID); 
    object comObj = null; 
    if (comType != null) 
    { 
    try 
    { 
     comObj = Activator.CreateInstance(comType); 
    } 
    catch (Exception ex) 
    { 
     Debug.Fail("Cannot create the script generator COM object due to the following exception: " + ex, ex.Message + "\n" + ex.StackTrace); 
     throw ex; 
    } 
    } 
    else 
    throw new ArgumentException("The GUID does not match a registetred COM object", "GUID"); 

    m_internalGenerator = comObj as IScriptGenerator; 
    if (m_internalGenerator == null) 
    { 
    Debug.Fail("The script generator doesn't support the required interface - IScriptGenerator"); 
    throw new InvalidCastException("The script generator with the GUID " + GUID + " doesn't support the required interface - IScriptGenerator"); 
    } 

} 

和TH是在執行C#代碼,以測試它的工作(這不是):

[Guid("EB46E31F-0961-4179-8A56-3895DDF2884E"), 
    ProgId("ScriptGeneratorExample.ScriptGenerator"), 
    ClassInterface(ClassInterfaceType.None), 
    ComSourceInterfaces(typeof(SOAAPIOLELib.IScriptGeneratorCallback))] 
    public class ScriptGenerator : IScriptGenerator 
    { 
    public void GetLastError(out string Error) 
    { 
     throw new NotImplementedException(); 
    } 
    public void Init() 
    { 
     // nothing to do 
    } 
    } 

回答

2

再論 - 感謝您的建議。

我終於可以自己解決問題了。我嘗試了上述建議並沒有取得任何進展。然後,我在「測試」代碼中更改了互操作的名稱空間 - 由於使用Tlbimp時使用不同的參數,它與主代碼中的名稱空間不同。這解決了這個問題。

下面是我的猜測:.Net創建COM對象,但是當它檢測到這實際上是一個.Net對象時,它會繞過COM層並直接進行通信。在這種情況下,不使用queryInterface(使用接口GUID),並且由於不同的C#名稱空間,接口會有所不同。

這意味着爲了支持與.Net代碼的集成,我需要將我的原始互操作程序集發佈到IDL之外。

謝謝, Inbar

0

我認爲你需要這個接口

[InterfaceType(ComInterfaceType.InterfaceIsDual)]