今天實(shí)際應(yīng)用時(shí),又進(jìn)行了一些測試,發(fā)現(xiàn)與以前看到資料中一些不同的表現(xiàn),見最后的【補(bǔ)充】部分
通常,實(shí)例化 COM 組件前(包括采用這一技術(shù)的 DLL/ActiveX 控件),都需要先用 regsvr32 注冊該組件或控件,從 XP sp2 開始,微軟提供了一種采用 manifest(文件清單)的方式來替代,詳見最后的 MSDN 參考資料。由于 COM 的注冊信息要寫入注冊表,一方面給 Win7 以后沒有管理員身份的應(yīng)用帶來了麻煩,另一個(gè)人一直存在的問題的就是所謂的DLL Hell,造成同一控件不同版本之間的干擾。MS 推出 .Net 時(shí)采用了程序集的方式來避免這個(gè)問題,同時(shí)也用文件清單的方式給 COM 帶來了新的調(diào)用方案,由于不需要將類信息寫入注冊表,COM 文件的放置位置也可以放到 exe 所在文件夾或它的子目錄中,自然也就避免了 DLL Hell 的問題。
文件清單是一個(gè) xml 格式的文本文件,其文件名后綴為 manifest(例如:程序名為 a.exe,則這個(gè)清單文件名為 a.exe.manifest),創(chuàng)建類實(shí)例時(shí),操作系統(tǒng)(實(shí)際上是 ole32.dll 的 CoCreateInstance API 函數(shù))會先檢查是否存在清單文件,如果存在有效的清單文件,從把從注冊表獲取 COM 信息的過程就轉(zhuǎn)變成了從清單文件中讀取。這個(gè)文件有很多作用,例如:指定運(yùn)行時(shí)的操作身份權(quán)限,是否使用系統(tǒng)主題,以及這里提到的描述 COM 注冊信息,... 等等
如果你用的是 vfp9,當(dāng)你 build 成 exe 后,用 ResHacker 打開這個(gè) exe 時(shí),你會發(fā)現(xiàn)存在一個(gè)序號為 24 的資源,其內(nèi)容為:
(圖一)
是不是很像前面提到的 MSDN 文章中的清單文件?如果你用 eXeScope 打開這個(gè) exe。會發(fā)現(xiàn)這個(gè) 24 號資源,它就是一個(gè)名為 manifest 清單的內(nèi)容:
(圖二)
也就是說,vfp9 的 exe 編譯時(shí),已經(jīng)嵌入了一個(gè)默認(rèn)的 manifest
由于 Windows 默認(rèn)內(nèi)置的 manifest 優(yōu)先于外部的 manifest,因此,我們只要寫一個(gè)添加了 COM 類聲明的新 manifest,重新編譯后的 exe 就實(shí)現(xiàn)了免注冊功能。有一點(diǎn)也許很多人還不知道:vfp9 在編譯 exe 時(shí),如果發(fā)現(xiàn)存在與要編譯的 exe 同名的 manifest 文件,就會用它替換掉默認(rèn)的清單文件。
下面我們就來驗(yàn)證一下:
1. 創(chuàng)建一個(gè)測試用 COM
a. 新建一項(xiàng)目 -> mycomm
b. 代碼 -> 新建,粘貼下面內(nèi)容并保存為 mycom.PRg
Define Class myComFunc as session olepublicFunction getName() Return 'dkfdtf'EndFuncEndDefine c. 編譯成 dll2. 創(chuàng)建一個(gè)測試用 EXE
a. 新建項(xiàng)目 -> test
b. 代碼 -> 新建,粘貼下面內(nèi)容并保存為 test.prg
Local oo, ccTry oo = NewObject('mycom.myComFunc') cc = oo.getName() MessageBox("RegFree COM: value = " + cc)Catch MessageBox('無法創(chuàng)建 COM 對象.')EndTry c. 編譯成 exe3. 運(yùn)行這個(gè) exe,應(yīng)該看到這樣一個(gè)對話框:
(圖三)
4. 現(xiàn)在用 Regsvr32 /u mycomm.dll 注銷掉這個(gè) COM,應(yīng)該看到這個(gè):
(圖四)
OK,一切都與未使用免注冊技術(shù)的情況相符。
現(xiàn)在開始實(shí)現(xiàn)免注冊功能,下面的內(nèi)容只是介紹如何實(shí)現(xiàn)你自己應(yīng)用程序?qū)崿F(xiàn)免注冊的步驟和方法;只想了解一下的話,只要下載后面的示例包運(yùn)行就可以了,其中包含了下面的代碼。
1. 在項(xiàng)目所在文件夾,新建一個(gè)文本文件,用前面提到的 ResHacker 打開 exe,找到 24號資源,將其中的內(nèi)容復(fù)制粘貼到新建的文本文件中,最后重命名為 test.exe.manifest
,然后用 RegFree 工具包 中的 mt 或 regsvr42 提取 mycom.dll 中注冊信息,加入其中,全部內(nèi)容如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><assemblyIdentity version="1.0.0.0" type="win32" name="Microsoft.VisualFoxPro" processorArchitecture="x86"/><description>Visual FoxPro</description><trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> <requestedExecutionLevel level="asInvoker" /> </requestedPrivileges> </security></trustInfo><file name="mycom.dll"><comClass progid = "mycom.myComFunc" clsid="{B20DF2B2-7810-4D08-8F3A-2B96786AF03E}" threadingModel="Apartment" /><typelib tlbid="{31358D79-374B-49BD-AC99-BFE798831194}" version="1.0" helpdir="" /></file><dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" language="*" processorArchitecture="x86" publicKeyToken="6595b64144ccf1df" /> </dependentAssembly></dependency></assembly>注釋:上面內(nèi)容直接從 test.exe 的 24 號資源復(fù)制過來,并加入了 <file> ... </file> COM 類描述信息部分;為簡明起見,這里只加入了必須的類描述元素,另外,如果 mycom.dll 與 test.exe 不在同一文件夾中,需要加上路徑部分,可以是相對或絕對路徑。增加的那些 GUID 值,你也可以直接在 mydll.vbr 中找到。如果是第三方控件,大部分情況下你沒有這個(gè) vbr 文件,所以我提供給你了上面的 RegFree 工具包來從 dll/ocx 中提取這些信息,用法很簡單:
用 mt 來提取:mt.exe -tlb:TBL文件名 -dll: DLL/OCX文件名 -out: 輸出結(jié)果文件名.txt 沒有專門提供TBL文件的話,TBL就用DLL/OCX 文件
用 regsvr42 提取:regsvr42.exe mycom.dll
兩個(gè)工具都有缺陷,mt 缺少 progid 項(xiàng)目信息,regsvr42 在 Win7 以上即使以管理員權(quán)限運(yùn)行也可能失敗,在 xp 下運(yùn)行沒問題
2. 重新編譯 test.exe,vfp 會用上面這個(gè)清單文件替換默認(rèn)的 manifest (24 號資源)
3. 運(yùn)行 test,應(yīng)該可以再次看到圖三的畫面。反復(fù)用 regsvr32 注冊和注銷 mycom.dll,結(jié)果應(yīng)該都一樣,這說明無論 COM 是否已注冊,都可正常使用;更極端一點(diǎn),你只復(fù)制 mycom.dll 和 test.exe 這兩個(gè)文件到其他有 vfp 運(yùn)行庫的機(jī)器上,不用注冊,就可以正常運(yùn)行。
驗(yàn)證示例:RegFree.rar
參考:
關(guān)于COM的Reg-Free(免注冊)技術(shù)簡介及實(shí)例講解
Registration-Free Activation of COM Components: A Walkthrough
regsvr42: Generate SxS Manifest Files from Native DLLs for Registration-Free COM
補(bǔ)充:
可以將類描述部分單獨(dú)放在清單文件中,不一定要寫入 exe 24 號資源中,也就是說,不更改 vfp 編譯 exe 時(shí)默認(rèn)生成的 24 號資源,另外單獨(dú)寫一個(gè)清單文件一起發(fā)布,不重復(fù)的部分不會相互干擾。與上面的示例包中的 mycom.dll 對應(yīng)的清單文件 test.exe.manifest 如下:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><file name="mycom.dll"><comClass progid="mycom.myComFunc" clsid="{B20DF2B2-7810-4D08-8F3A-2B96786AF03E}" tlbid="{31358D79-374B-49BD-AC99-BFE798831194}" /></file></assembly>不過要記住,前面說過,vfp 編譯時(shí)如果發(fā)現(xiàn)項(xiàng)目文件夾中存在同名的 manifest 文件,就會用它替換默認(rèn)的清單。所以,如果要單獨(dú)發(fā)布清單文件(為了便于 COM 版本更新時(shí)只更新 dll 而不用更新 exe),就不要把這個(gè)文件放在開發(fā)機(jī)器上項(xiàng)目所在文件夾中。否則,還是像前面描述的那樣比較可靠,將類描述信息插入到復(fù)制的默認(rèn)清單文件中,并在更新 COM 時(shí),同時(shí)發(fā)布更新的 COM 和重新編譯的 EXE 文件。
補(bǔ)充2:
找到一個(gè)比較完美的提取并自動(dòng)生成清單文件的工具:
http://www.rdctools.com/Downloads/SetupRDCToolsCOMManifestBuilderPro.exe
完全免費(fèi)(首次運(yùn)行時(shí)會顯示要激活,只要點(diǎn)擊獲取激活碼按鈕,會自動(dòng)連接到官網(wǎng),顯示你的激活碼,不需要輸入任何信息)
該工具還有其他一些功能:檢查/添加數(shù)字簽名,壓縮,檢查/注冊/注銷 COM/OCX/DLL,等等
|
新聞熱點(diǎn)
疑難解答
圖片精選