簡體   English   中英

使用ExeCOMServer時,無法將類型為“...”的COM對象轉換為接口類型“...”

[英]Unable to cast COM object of type '…' to interface type '…' while using an ExeCOMServer

我正在使用這個exe com服務器:

https://cfx.svn.codeplex.com/svn/Visual%20Studio%202008/CSExeCOMServer/ExeCOMServer.cs

  • 我的編程是一個com應用程序
  • 采用另一個com對象的我的com方法是void Init(AppsScriptRunningContext rc);
  • 在這個方法中,我嘗試讀出一個屬性並得到此錯誤

無法將“AppsScriptLib.AppsScriptRunningContextClass”類型的COM對象強制轉換為接口類型“AppsScriptLib.IAppsScriptRunningContext”。 此操作失敗,因為對IID為“{4D2E5723-87C2-49C1-AA28-ED2D88275100}”的接口的COM組件的QueryInterface調用由於以下錯誤而失敗:不支持此類接口(HRESULT異常:0x80004002(E_NOINTERFACE))

如果我的應用程序不是com服務器而是普通的com應用程序,則沒有錯誤。 這就是為什么我認為錯誤是由exe com服務器產生的。

https://cfx.svn.codeplex.com/svn/Visual%20Studio%202008/CSExeCOMServer/ExeCOMServer.cs

問候,克里斯

這是一個非常令人遺憾的代碼示例,成功的可能性非常接近於零。 它是MSDN論壇支持小組的產品,他們的工作未在Microsoft進行同行評審。 一位團隊成員后來承認這不是正確的方法。

該代碼的一個問題是它完全忽略了注冊服務.RegisterTypeForComClients()方法的MSDN文檔中的備注:

請注意,不支持使用平台調用來調用非托管CoRegisterClassObject和CoDisconnectObject方法來注冊和取消注冊COM對象。

不幸的是,沒有解釋為什么它不受支持。 關鍵問題是COM接口總是需要在進程外激活情況下進行封送。 這是通過在客戶端創建代理來完成的,該代理是一個接口實例,它具有與原始接口完全相同的方法,但其實現的方法通過RPC將方法的參數發送給另一個進程。 在服務器端,存根執行相同但相反的角色,使用方法參數構建堆棧幀並進行實際的方法調用。

在.NET中創建代理和存根很容易,反射使它變得簡單。 由構建在框架中的Remoting管道完成。 然而,它在COM中並不容易,它沒有任何類似於反射的東西。 它有兩種基本的完成方式,首先是用IDL語言編寫COM接口定義並用midl.exe編譯它。 這可以自動生成執行編組的C源代碼,您可以從中構建DLL。 然后需要在HKCR \\ Interface注冊表項中正確注冊該DLL,以便COM可以在需要封送接口時查找並加載DLL。 如果您的接口派生自IDispatch並將其自身限制為OLE自動化兼容的參數類型,則可以使用第二種方法。 然后,您可以生成類型庫並使用標准編組器。 這需要注冊類型庫,以及HKCR \\ Interface中的相應鍵,以便COM知道它。

這是.NET進程外服務器中不會​​發生的部分。 您沒有midl.exe來幫助您生成代理/存根DLL,並且您沒有獲得使用標准編組器的注冊幫助。 這是錯誤消息的真正含義,E_NOINTERFACE在這里真的意味着它找不到任何方法來編組接口。 是的,糟糕的錯誤消息。

.NET中正式支持的創建進程外COM服務器的方法是將其注冊到COM +。 使用System.EnterpriseServices.ServicedComponent類作為基類。 MSDN庫文章在這里

我得到了一個建議,在主線程中進行更改,這對我有所幫助!

在主線程中查找(主要在“Program.cs”中)[STAThread]行並將其更改為[MTAThread]。

暫無
暫無

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

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