2011-04-14 66 views
9

在我的節目我用COM +後期綁定C#4.0

Type comObjectType = Type.GetTypeFromProgID(progId, true); 
object comObject = Activator.CreateInstance(comObjectType); 

,然後使用反射調用的方法之一創建COM +對象動態地(後期綁定)

object result = comObjectType.InvokeMember(MethodToActivate, BindingFlags.InvokeMethod, null, comObjec, new object[] {....}); 

它的工作原理馬麗娟在.net 1.1/2.0/3.5

現在我試圖在爲.NET 4.0編譯的同一臺計算機(Windows XP)上運行相同的代碼,但我有一個

Exception: Method 'System.__ComObject.{MethodName}' not found. 

我對大多數Com +對象(不是所有)都有例外。 有誰知道這是什麼問題? 爲什麼我在FW 4.0環境中遇到異常? 我該怎麼做才能避免它?

非常感謝, 丹尼爾

經過一番詳細的調查我發現,一些COM +代理爲System._ComObject(這些都是原生的,我想),有的爲System.Runtime.Remoting.Proxies._TransparentProxy創建創建(我認爲那些是.Net Com +對象)。方法調用適用於創建爲System._ComObject而不適用於System.Runtime.Remoting.Proxies._TransparentProxy的那些調用。 最有趣的事實是,在.Net 2.0中,所有對象都以相同的方式創建(_ComObject_TransparentProxy),但方法調用確實工作正常。 另一個有趣的事實是,我可以用幾點思考

((System.EnterpriseServices.RemoteServicedComponentProxy)((((System.Runtime.Remoting.Proxies.__TransparentProxy)(ObjectToActivate)))._rp)).ProxiedType.GetMethods()

我想對於一些時刻,它可能是一個安全問題看在調試器中「失蹤」的方法,但我運行代碼WindowsService登錄作爲具有管理員權限的用戶

+0

您是否檢查過任何32/64位問題?也許你的程序是64位的,因此打到64位COM註冊表(沒有人住:-)? – 2011-04-27 06:17:03

+0

我不認爲這是一個32/34位的問題,我的本地機器是32位,遠程服務器 – 2011-04-27 07:14:53

+0

對32/64位也是如此。現在,它看起來像你的COM服務器不在進程中或具有特定的線程模型(因此代理)。你能提供更多細節嗎?他們託管在過程之外嗎?在組件服務中?那麼Invoke參數呢?你確定沒有歧義嗎?那BindingFlags呢?你不需要Public | Instance嗎? – 2011-04-27 07:49:12

回答

6

我發現COM類型創建中的.NET FW存在差異,並且據我瞭解,只有.NET COM對象存在差異。當COM對象類型是與

Type comObjectType = Type.GetTypeFromProgID(progId, true); 

時返回在.NET 1.1/2.0/3.5爲對象的實際.NET類型,所以在它的方法調用沒有問題,但在類型創建.NET 4.0 System.__ComObject類型返回所以代碼

result = comObjectType.InvokeMember(
    MethodToActivate, BindingFlags.InvokeMethod, null, ObjectToActivate, InputParams); 

失敗,未發現異常的方法。

,我已經找到了解決辦法如下:

Type comObjectType = Type.GetTypeFromProgID(progId, true);   
object comObject = Activator.CreateInstance(comObjectType); 

// here the real object type is returned 
Type acctualObjectType = comObject.GetType(); 
result = acctualObjectType.InvokeMember(
    "MethodToActivate", BindingFlags.InvokeMethod, null, comObject, InputParams); 

此代碼工作正常適用於所有環境。

+0

有趣的 - 我實際上發佈了一個答案,以前我懷疑會有幫助的諷刺刪除它後閱讀另一個問題,說服我我錯了! - 無論如何,很高興你的問題得到了解決。 – Justin 2011-04-27 11:38:02

+0

在你的解決方案代碼中,comObject應該和ObjectToActivate是一樣嗎? – 2014-09-12 20:43:46

+0

是的,ObjectToActivate是一個返回comObject的屬性。 – 2014-09-13 21:42:29

1

我不確定爲什麼您的以前運行的代碼不再有效,但我相信在.Net 4.0中,您可以使用IDispatch /後期綁定通過dynamic類型調用COM方法 - 請參閱Does C# .NET support IDispatch late binding?

+0

我想過這種解決方案,但它是不能接受的對我來說,因爲我需要爲所有.Net FW版本運行相同的代碼。它是運行在不同環境中的核心庫的一部分 – 2011-04-27 07:18:27

+0

@Daniel:不管它是否令人滿意,是否使用'dynamic'仍顯示錯誤? – Gabe 2011-04-27 08:27:34

+0

我嘗試了一個與'動態'樣本,它的工作原理(但對我來說無用(:) – 2011-04-27 08:28:49