如何使用C#調用U8的COM組件之 一前言


前言

我們知道,U8的大部分功能使用VB6語言開發。所以整個U8功能都是基於COM組件技術實現的。對於使用VB6語言開發來說,沒有什么問題。我們可以直接使用CreateObject("類名"),動態創建我們需要的組件,然后直接調用其方法。

'創建登錄對象
dim c=CrateObject("U8Login.clsLogin")
'調用登錄方法
c.login()
這樣的開發有點類似腳本語言,非常靈活。但有一個問題,那就是不能使用上IDE提供的類型安全和友好提示,並且如果你沒有源代碼的情況下,非常難知道類名對應的函數等等。

舍不得的IDE提示

如果想使用IDE的友好提示,在VB6中,我們一般會引用需要的COM組件,然后ctrl+j的時候就能自動出來函數方法了。

為了能夠使用代碼提示功能,且能夠使用C#開發。就必須使用interop技術,技術本身這里先不多解釋,就通俗的描述一下:
簡單說,為了能夠使用NET調用COM組件,必須引用一些DLL文件,這些文件一般都放在C:\U8Soft\Interop下面。
這些文件一般都是以Interop單詞加一個點開頭的文件,或者AxInterop開頭的。
例如:Interop.U8Login.dll,這個文件就是COM版本的U8登錄組件。
這些文件中包含了所有COM組件提供的功能類和函數,並准確的給出了具體參數規則。和普通的NET類庫是完全一樣的。引用之后可以直接new這些類對象,並調用對應的函數直接使用。

Interop的由來

反編譯Interop

那么這些Interop文件又是怎么來的呢?當然不是手寫出來,他是通過命令行工具得到的,或者你在VS中引用COM組件后,VS會自動幫你做出來這些文件。具體的操作可以百度,這里不展開。
Interop文件如果進行反編譯,你會發現她就是NET語言開發的,只是沒有具體的實現代碼,函數體都是空的,並且都是一些類的聲明,其中每個接口類上面,會有一些GUID的屬性。這些其實就是COM組件的編碼了,或者咱們叫唯一Id,主鍵等等啦。window就是通過這個id,然后到注冊表這個大數據庫里面去select一下,看看這個Id對應的dll文件到底在哪里,然后自動根據注冊表的文件地址,去初始化我們的類。
所以說Interop就是一個提供類型安全和GUID對應的類庫文件。有了類型安全,就有了IDE自動提示,有了GUID就能讓windows找到COM,微軟提供的這個技術還是蠻不錯的,但是也存在着不完美的問題。

Interop存在的問題

問題一,拖家帶口的Interop生成過程

如果你使用百度提供的方法去生成Interop文件后,你會發現一個很奇怪的事情,就是本來我想生成一個COM組件的Interop文件,結果生成出來的Interop文件好多個。
比如我想自己生成一個U8login.dll的Interop文件,結果搞出來一看,居然還有Interop.msxml2.dll和adodb.dll文件。那么這是怎么回事呢?
其實這里需要換一個角度理解問題。因為在NET里面,類庫都是包裝在DLL里面的,所以一個DLL就提供一套類庫功能,比如log4net.dll,就提供日志功能。
以此類推,每一個COM組件,微軟都認為應該有一個獨立的DLL文件,所以U8login.dll封裝以后,就會理所應當的變成Interop.U8Login.dll,其中也只包含了Login組件的類和函數。
可是,當COM組件引用了其他的COM組件,或者說,如果U8login中某個函數的返回值或者參數居然是另一個COM組件時怎么辦呢?比如ado組件中的cn和rs都是我們最常用的參數類型。如果U8Login的某個函數需要返回cn。這時候cn對應的類功能,應該放在哪個文件里面呢?
微軟在這個時候就顯示出來他的可怕智慧,他就會非常智能(傻逼)地給你把需要的COM組件,逐一,自動地生成對應的Interop文件,然后讓Interop.U8Login.dll去引用這些Interop.XXX.dll。注意這句話里面的引用這個動詞。
比如,我們先Interop一下U8login.dll,然后得到Interop.U8Login.dll文件,隨后需要Interop另個一COM組件,假設是VoucherCO_SA.dll,這是一個銷售模塊最核心的保存類組件,API就是直接調用他去保存單據的。當我們把他Interop一下后,會發現,居然又是一大堆Interop文件,其中可能還有Interop.U8Login.dll!這個時候就非常尷尬了,因為從引用的角度考慮,我們希望自己的Interop新文件最好去引用之前已經生成好的勞動成果,而不是每次都拖家帶口的搞出來一大家子DLL。

問題二,強命名Interop文件后的DLL陷阱

如果我們翻看C:\U8soft\interop文件夾下的文件,你會發現,其中的Interop.U8Login.dll是有強命名的,而密匙文件snk也沒有給咱們,同時目錄下面還有一個叫做ADODB.dll的文件,居然也有強命名。
連帶着問題一,就會發現,如果我們去生成VoucherCo_SA.dll,由於拖家帶口,此時你就會得到兩個Interop.U8Login.dll文件,一個是沒有強命名的微軟自動生出來的,一個是總部標准提供的,而Interop.VoucherCo_SA.dll引用的,是無強命名的那個文件。
這時候,就會發現整個環境已經混亂了,我們進入了Dll陷阱中,即同名文件,同類庫,不同強命名。

問題三,該死的WIN7和該死的ADODB

如果你使用的是WIN7系列的操作系統,那么恭喜你了,在Interop生成這個環節,你會非常非常郁悶,因為只要遇到引用了ADODB.dll的COM組件,你根本Interop不出來文件,包括Window2008系列的系統。
核心原因是ADODB這個組件在win7時代被改過,具體這里不展開說了,簡單說,在這種系統下編譯VB6組件程序,不能在XP下使用,InteropADODB相關組件,會直接失敗。加之拖家帶口問題,你基本就沒有幾個COM組件能搞出來了。
這個問題在Win2003下和Win10下都不存在,微軟后來吸取教訓修改了Win10系統中的ADODB組件。所以如果開發的話,必須准備兩個環境,一個Win10虛擬機,一個Win2008R2虛擬機,我一般使用08R2虛擬機進行程序開發,Win10就測試發版和COMInterop用。

本章完,請看第二章

如何使用C#調用U8的COM組件之二 利器與初探


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM