2013-07-11 59 views
1

這個問題是this question的續篇C#程序如何使用任何版本的COM DLL?

我們正在創建一個用C++編寫的dll,提供對某些硬件的訪問。這個DLL實現並使用COM接口訪問。我們也有一個C#程序,它通過COM對象使用這個DLL。

我們遇到了版本問題。事實上,在運行C#程序時,它絕對要使用編譯時使用的確切COM/C++ dll版本。即如果C#程序是使用COM/C++ dll 1.2.3.4編譯的,那麼程序將拒絕使用COM/C++ dll 1.2.3.5運行。

Unhandled Exception: System.TypeInitializationException: The type initializer for 'MyDllVerify.App' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'MyCorp.MyDll.Interop, Version=1.2.3.4, Culture 
=neutral, PublicKeyToken=ced78d295d1e0f2b' or one of its dependencies. The system cannot find the file specified. 
File name: 'MyCorp.MyDll.Interop, Version=1.2.3.4, Culture=neutral, PublicKey Token=ced78d295d1e0f2b' at MyDllVerify.App..cctor() 

我想指示C#程序使用任何COM/C++ DLL版本1.2.anything。

我在哪裏可以在C#項目中配置?

回答

3

我建議你不要直接引用你的C#項目中的COM DLL。如果你這樣做,在構建時總會生成一個新的COM-interop-dll。這可能會導致很多問題。

這將是一個更好的方法來創建COM-interop-dll,將其存儲在庫文件夾中,並將此庫引用到C#項目中。儘可能保持此COM-interop-dll靜態。如果你這樣做,只要你的界面不改變,你可以儘可能多地替換使用的COM-dll。你可以嘗試操作這個互操作程序集,併爲1.2。*版進行版本檢查,如果你真的想這樣做(我不推薦這樣做,它可能會導致嚴重的混淆)。

說明: COM-interop-dll是一個常規的.NET程序集。它的工作方式類似於C#代碼和要在C#代碼中使用的COM-C++代碼之間的包裝。

COM-interop-dll不必註冊COM。你可以安裝這個程序集很多次你喜歡。但它需要你的COM-DLL註冊COM。

有用的工具:

  • TLBIMP
  • regasm
  • SN
3

沒有什麼是從我記錄在你前面的問題的方式不同。您仍然使用<bindingRedirect>來允許加載錯誤版本的互操作程序集。

這是相當不可能的在實踐中工作,搞亂DLL地獄當你使用COM是非常不明智的。如果您使用早期綁定,則COM無法驗證您是否正在調用正確的方法。與.NET不同的是,抖動可以在運行時根據程序集中的元數據進行檢查。如果C++程序員做對了,那麼他改變了他改變的類型的指導。這將使你的代碼被E_NOINTERFACE炸彈,因爲你將使用舊版本的GUID。

如果他不這樣做,不幸的是,這種方式太常見了,那麼你的程序很可能會碰到一些像AccessViolationException這樣令人討厭的東西。或者更糟糕的是,它不會崩潰,但會調用完全錯誤的方法。

失效模式更良性,當您使用後期綁定,你會得到當方法不存在,或者如果它的參數已經改變了IDispatch錯誤之一。並不是說這最終解決了任何問題,你仍然有一個不起作用的程序。只有當你喜歡危險地生活時,纔會像這樣混淆DLL地獄。