如何使用C#呼叫U8的COM元件之二 利器與初探
前一章(點選可以看前一章內容),我們講解了Interop的三大問題,本章將引入利器,對這三個問題進行初探,並加以解決
善功必先利器
工具一 SpyStudio
這是我最近發現的一個特別牛逼的軟體,主要用來HOOK程式,實時分析程式呼叫了那些api,讀取了那些檔案,用到了那些COM元件,讀取了那些登錄檔。特別適合進行軟體綠化,因為它能直接匯出vmware thinapp,簡直是神一樣的存在,可惜不能在Win10下正常使用。但是綠化後的程式可以在各種系統下執行。
工具二 ILMergeGUI_Portable和ILMerge
用於將多個NET的DLL元件合併到一起,本來是一個命令列工具,後來我找到一個GUI的小程式,可以托拉拽了,特別強大和方便。
工具三 DotNETHelper
這也是一個殺手級別的利器,主要用來將NET反編譯成IL檔案,然後修改IL後,再次編譯成DLL。我主要用它解決引用錯誤問題。因為Interop檔案不能很完美反編譯成C#語言,所以很多工作我都是在IL級別操作的。
工具四 TotalCmd
因為後期主要是對各種檔案的操作,所以最好準備一個TC工具,可以非常方便的管理檔案。對於這個軟體可以說也是神級別的了,我就不多說了。自己百度吧。
工具五 Mono.Cecil
準確的說,這不是一個工具了,而是一個NET的類庫,由Mono提供,可以修改Net程式的DLL檔案,功能比DotHelper還要強大。因為需要對Interop檔案進行批量的處理,而IL操作實在是太麻煩了,所以直接用這個類庫,通過程式設計的方式,把我想修改的內容寫成程式碼,然後執行,全部搞定!!
工具使用
以上的5個工具,除了SpyStudio暫時用不到,其他的工具,是下面將會用到的主要工具,所以希望大家提前去百度學習一下如何使用,這裡不展開。畢竟也不是非常複雜,過程中我會盡量截圖,讓大家看的清除一些。
Interop檔案引用修復初探
反編譯觀察
有了工具,我們就可以分析Interop檔案了,首先拿出DotNetHelper,把Interop.U8Login.dll反編譯後,看一下IL檔案的開始部分資訊。
DOTNETHELPER
檔案的內容很多,但是我們主要關注開頭部分,因為開頭部分是引用部分,相當於我們開發C#時,引用程式集那個部分的功能,具體的格式如下:
// Metadata version: v2.0.50727 .assembly extern mscorlib { .publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4.. .ver 2:0:0:0 } .assembly extern ADODB { .publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....: .ver 7:0:3300:0 }
我們這裡發現Interop.U8Login.dll 引用了兩個元件,一個是2.0的mscorlib,也就是framewor 2.0的基本環境。一個是ADODB,版本7.0。並且我們發現ADDOB有兩個特點。
1、ADODB的這個引用帶有強命名,.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )
2、ADODB這個引用前面沒有Interop單詞,.assembly extern ADODB,這個特徵很重要,有時候我們在處理Interop.VBA.dll的時候你就會發現,有的引用居然是VBA.dll,有的是Interop.VBA.dll
分析正確檔案的特點
我們再看一下,正確引用了Interop.U8Login.dll的其他Interop檔案,比如下面就是我自己編譯的Interop.USERPCO.dll,該類庫引用了U8Login元件,這個類庫也是非常重要的一個類,主要完成庫存單據的儲存功能。是API裡面最核心的呼叫類。
// Metadata version: v2.0.50727
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 2:0:0:0
}
//這裡的引用,publickey和U8login的ADODB引用是完全一樣的
.assembly extern ADODB
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
.ver 7:0:3300:0
}
.assembly extern Interop.VBA
{
.ver 6:0:0:0
}
//這裡的引用,沒有publickey
.assembly extern Interop.USCOMMON
{
.ver 2:1:0:0
}
//注意這裡的引用,有publickey
.assembly extern Interop.U8Login
{
.publickeytoken = (79 A4 E7 AD 54 EE AB CA ) // y...T...
.ver 1:14:0:0
}
.assembly extern Interop.MSXML2
{
.ver 3:0:0:0
}
注意U8Login的強命名還有版本號 ,.publickeytoken = (79 A4 E7 AD 54 EE AB CA ) .ver 1:14:0:0
注意ADODB的強命名和版本號,這兩個值是(.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) .ver 7:0:3300:0 ),且和U8Login使用的ADODB完全一樣,這樣的檔案,就是正確的,因為如果U8Login有返回值是ADODB中的類,那麼這個Interop檔案可以正常操作,不會出現型別轉換失敗的問題,因為他們引用的是同一個ADODB檔案。
錯誤檔案的特徵
再看一個我們自己生成的Interop後最容易遇到的問題,往往我們自己生成Interop 檔案以後,很有可能是這樣的
//前面的我就忽略不貼出來了,直接看關鍵的U8Login的引用
.assembly extern Interop.U8Login
{
.ver 1:29:0:0
}
正確的應該如下
.assembly extern Interop.U8Login
{
.publickeytoken = (79 A4 E7 AD 54 EE AB CA ) // y...T...
.ver 1:14:0:0
}
這裡之所以不一致,就是前文說的拖家帶口問題導致的,其實你仔細看,就會發現在你生成的Interop檔案對應的目錄裡面,居然還有一個Interop.U8Login.dll,而這個檔案就是版本1.29那個檔案。而NET程式是絕對不能引用兩個同名檔案的。所以必須將公用引用檔案保持一致。
到此我們發現了正確檔案的基本特徵:
1、公用檔案,比如ADODB,他們引用的名稱,版本號,強命名都是完全一樣的
2、彼此關聯的檔案,比如某DLL引用了Interop.U8Login.dll,必須保證某DLL中U8login的版本和強命名還有名稱和原版的Interop.U8Login一致。
Interop引用錯誤的問題修改
毛爺爺教導我們,知錯不改,不是好同志!既然我們知道了錯誤的根本原因,那麼下面就開始做一名真正的好同志。
修改方法1 反編譯法
之前說過,Interop.U8Login.dll不是能完美反編譯成C#的,但是如果你願意手工干預,通過後期的修改,這個專案可以完美的變成一個標準C#類庫專案,然後通過修改引用,再次編譯就好了。可惜,我不認為有人會這麼幹,因為Interop檔案實在太多了,修改工作量巨大,錯曾經嘗試過幾次,最後都放棄了。
修改方法2 命令列引數法
正統的解決方案微軟其實是給出來的,就是通過在使用Tlbimp.exe這個命令列的時候,使用/reference 引數
Tlbimp.exe C:\U8Soft\Ufcomsql\U8Login.dll /reference:"C:\U8Soft\Interop\MSXML2.dll"
Tlbimp.exe C:\U8Soft\Ufcomsql\USERPCO.dll /reference:"C:\U8Soft\Interop\Interop.U8Login.dll" /reference:"C:\U8Soft\Interop\MSXML2.dll"
上面的程式碼,展示瞭如何使用多個已有類庫檔案,解決引用錯誤。這個方法真的非常不錯,我以前也使用,後來覺得還是改IL比較有成就感,所以就不怎麼用這個方法。但是我還是強力推薦該方法。
修改方法3 IL修改法
之前的整個研究過程,都是基於IL進行,所以我最早使用的就是DotNetHelper工具進行IL修改去解決這個問題的。速度也比較快,反編譯,開啟IL檔案,找到錯誤點,修改,重新編譯,問題解決。(這裡補充一下,因為ocx控制元件使用AxImp工具生成AxInterop檔案,但是這個命令列工具沒有引用引數reference,所以只能使用IL修復法。)修改的過程如下:
//前面的我就忽略不貼出來了,直接看關鍵的U8Login的引用
.assembly extern Interop.U8Login
{
.ver 1:29:0:0
}
正確的應該如下
.assembly extern Interop.U8Login
{
.publickeytoken = (79 A4 E7 AD 54 EE AB CA ) // y...T...
.ver 1:14:0:0
}
本章完
下一章,開始講解在面對繁多的U8版本和繁多的Interop時,面臨的新問題