OCX 打包 CAB 與 JS 調(diào)用詳細(xì)教程

最近在做一個 WEB 項目,需要調(diào)用 OCX 進(jìn)行連接讀卡器讀卡。本來并不想用 OCX 技術(shù),因為 ActiveX 技術(shù)是微軟出品,這樣就導(dǎo)致整個系統(tǒng)只能使用 IE 瀏覽器(其他瀏覽器可以通過插件的形式支持 OCX 的調(diào)用)。但嘗試了很多方法調(diào)用客戶端 DLL 發(fā)現(xiàn)都走不通。最后無奈之下,才打算研究 OCX 技術(shù)。

網(wǎng)上都說 ActiveX 技術(shù)很麻煩,會出現(xiàn)各種錯誤,不做的時候不知道,真正需要研究時候,才發(fā)現(xiàn)確實如此。主要問題是,報錯和問題的真正原因沒有關(guān)系或者說關(guān)系不大,甚至很多時候沒有報錯,只有不斷嘗試。

言歸正傳,下面來講一下如何搞定 OCX。

首先先聲明,本教程只關(guān)于 OCX 打包 CAB 和 JS 調(diào)用 OCX,這里不探討如何通過 C++ 寫 OCX。因為本人只做 Java 開發(fā),對于C++ 并沒有研究。

開發(fā)系統(tǒng):win8.1 64位

測試通過系統(tǒng):win7 64 位、win8.1 64位、xp 32位

OCX 和 CAB 的關(guān)系。

大家知道,得到 OCX 之后,如果想要調(diào)用,首先要注冊。在不注冊的情況下,沒辦法調(diào)用 OCX 。

最簡單的注冊辦法是手動注冊。手動注冊需要在命令行操作。對于開發(fā)人員來說,多多少少要和命令行打交道,可能沒有問題,不過對于使用我們系統(tǒng)的客戶來說,讓他進(jìn)行命令行操作的確不合適。不管我們文檔寫得多么詳細(xì),對客戶來說這都是不友好的,而且手動注冊也設(shè)計到安全性問題。所以就需要在客戶不知情的情況下自動對 OCX 注冊。這也就是 CAB 的作用。

手動注冊 OCX

我們假設(shè),OCX 所在的目錄是:D:/ocx/xpbutton/xpbutton.ocx

通過 regsvr32 xpbutton.ocx ,這樣我們就手動注冊了 OCX。

如果想卸載 OCX,我們可以反注冊:regsvr32 /u xpbutton.ocx 。

注冊和卸載,我們都需要以管理員身份運(yùn)行 cmd 控制臺。-- 這里特別需要注意!

如果在注冊時候出現(xiàn)下面的錯誤:

1.首先查看是否以管理員身份運(yùn)行 CMD。

2.如果還是不行,可以考慮將相應(yīng)的 OCX 放到系統(tǒng)目錄下

a). 32 位系統(tǒng)放到?C:\Windows\System32

b). 64 位系統(tǒng)放到?C:\Windows\SysWOW64

3.如果還是報錯,那可以確定是缺少 DLL 導(dǎo)致的。各位可以下載一個工具:Dependency Walker。

這里的教程,看少了哪些 DLL,去網(wǎng)上下載這些 DLL,這些 DLL 就是你必須要和 OCX 一起打包到 CAB 壓縮包里面去的。因為你自己電腦少了,說明客戶電腦也同樣可能會少這些 DLL。

這里需要注意的是:首選的是和你系統(tǒng)相同位數(shù)的 DLL,肯定不會錯,實在找不到 64 位的,才考慮 32 位的版本。

下載了 DLL 后,將 DLL 存放到上面第二步提到的系統(tǒng)文件夾下面,然后再注冊。

OCX 打包 CAB

首先下載 OCX 打包簽名工具:ocx 打包簽名工具,? 訪問密碼 ddb4。

將需要簽名和打包的 OCX 和命令放到相同文件夾。

制作簽名證書:

在命令行運(yùn)行下面命令:

1. 執(zhí)行命令:

[plain]view plaincopy

makecert.exe?-ss?xpbutton?-n?"CN=這里隨便"?-sv?.\xpbutton.pvk?-r?.\xpbutton.cer

輸入三次,密碼,查看控制臺出現(xiàn) Succeeded 表示成功。

此時生成文件:xpbutton.cert 和 xpbutton.pvk

2. 運(yùn)行命令:

[plain]view plaincopy

Cert2Spc.exe?.\xpbutton.cer?.\xpbutton.spc

查看控制臺,出現(xiàn) Succeeded 表示成功。

此時會生成文件:xpbutton.spc

兩條命令結(jié)束,我們一共得到三個文件:xpbutton.cer、xpbutton.pvk、xpbutton.spc

對 OCX 進(jìn)行簽名

打包 CAB 之前,首先需要對 OCX 本身進(jìn)行簽名操作,這一步很重要,如果沒做,你可能就犯錯了。

3. 運(yùn)行命令:signtool signwizard

如果想要填寫時間戳,可以填寫以下地址:http://timestamp.verisign.com/scripts/timstamp.dll

等待片刻,出現(xiàn)下面提示,則表示對 ocx 簽名完成。

控制臺出現(xiàn):Successfully completed signing wizard:<> 表示成功。

編寫 INF 文件

INF 文件也是一個重點(diǎn),如果編寫錯誤,則不能正確打包。(各位可以下載本人編寫的 INF 文件,在此基礎(chǔ)上進(jìn)行修改,保證 INF 文件的正確性)

INF 參考文件下載地址:OCX inf 文件,訪問密碼 49de。

如果打包 CAB 沒有問題 ocx 、dll 都會下載到 c:/windows/ocx/ 目錄下,方便各位卸載 ocx ,刪除 dll 文件。

[version]

signature="$CHICAGO$"

AdvancedINF=2.0

[DefaultInstall]

CopyFiles=files

RegisterOCXs=RegisterFiles

[DefaultUninstall]

cleanup=1

Delfiles=files

UnRegisterOCXs=RegisterFiles

[SourceDisksNames]

1 = %DiskName%, "xpbutton.cab", 1

[SourceDisksFiles]

xpbutton.ocx=1

msvcrtd.dll=1

mfc42d.dll=1

mfco42d.dll=1

[RegisterFiles]

%30%\Windows\ocx\xpbutton.ocx

[DestinationDirs]

files=30, Windows\ocx

[files]

xpbutton.ocx=xpbutton.ocx

msvcrtd.dll=msvcrtd.dll

mfc42d.dll=mfc42d.dll

mfco42d.dll=mfco42d.dll

[xpbutton.ocx]

file=thiscab

clsid={134EE1CC-4B8A-4E74-8C41-F4990065E2E1}

FileVersion=1,0,0,1

RegisterServer=yes

[msvcrtd.dll]

file=thiscab

FileVersion=6.0.8337.0

[mfc42d.dll]

file=thiscab

FileVersion=6.0.8168.0

[mcfo42d.dll]

file=thiscab

FileVersion=6.0.8267.0

[Strings]

DiskName="Windows\ocx"

以上是本人的 inf 文件。解釋幾個部分。

1.這里面添加了 3 個dll,如果各位不需要將 dll 打包到 cab ,則可以參照上面藍(lán)色的部分。如果沒有 mcfo42d.dll 則將藍(lán)色的部分全部刪除,其余的不動。以此類推。

2.

[plain]view plaincopy

[xpbutton.ocx]

file=thiscab

clsid={134EE1CC-4B8A-4E74-8C41-F4990065E2E1}

FileVersion=1,0,0,1

RegisterServer=yes

進(jìn)行簡單解釋:

file=thiscab 照搬照抄,不解釋。由于是 64 位系統(tǒng),本人測試這么寫沒問題。

32 位系統(tǒng)也可以這樣寫:?file-win32-x86=thiscab

clsid 這里,最簡單的辦法是找到 ocx 的來源,詢問制作 ocx 作者,他們知道這里應(yīng)該填寫什么。

如果找不到制作人,也有辦法,參照前文手動注冊 ocx ,然后查看搜索注冊表:xpbutton

找到左邊類似的注冊表結(jié)構(gòu),然后?134EE1CC-4B8A-4E74-8C41-F4990065E2E1 將是我們需要的 clsid 了。

注意:本人在?C:\Windows\ocx\?目錄下注冊的 xpbutton.ocx 文件。所以上面右圖地址才會是C:\Windows\ocx\xpbutton.ocx

FileVersion 也是一樣,最好的辦法,找到 ocx 的來源(開發(fā)者),確定版本號,編寫 ocx 時,代碼中會有 ocx 對應(yīng)的版本號。當(dāng)初和 C 溝通時,看過 ocx 的 C++ 代碼,里面有對應(yīng)的版本信息。這里的版本信息必須和 OCX 的版本信息一致。

RegisterServer=yes 表示下載下來后自動注冊此 ocx 。

大家可以看到我下面的 dll 文件的代碼中都沒有這一句,意思是 dll 下載下來后不需要注冊,如果各位的 dll 也需要注冊,對應(yīng) dll 區(qū)域也需要添加此語句。

3.對 INF 文件中綠色的部分進(jìn)行解釋

綠色的部分,表示 dll 的版本號,如何確定 dll 版本號。其實很簡單。

找到對應(yīng)的 dll 右擊,查看屬性,這里的文件版本,就是我們需要的版本號,請注意,不是產(chǎn)品版本。

OCX 打包 CAB 文件

4.運(yùn)行命令:

[plain]view plaincopy

CABARC.EXE?-s?6144?n?xpbutton.cab?xpbutton.ocx?xpbutton.inf

需要解釋一下這條命令:是將 xpbutton.ocx xpbutton.inf 文件打包成 xpbutton.cab 文件,如果我們需要將額外的 dll 也打包到 cab 里面,那這樣寫:CABARC.EXE -s 6144 n xpbutton.cab xpbutton.ocx msvcrtd.dll xpbutton.inf 以此類推。

對 CAB 文件簽名

對?CAB?文件簽名的過程,可以查看上文對?OCX?文件簽名的過程,除了第一步此處選擇的是?CAB?文件之外。其余步驟完全相同。

到目前為止,我們已經(jīng)將 OCX 打包成 CAB ,但是到現(xiàn)在還不行。很多教程都到此為止,其實 OCX 的繁瑣遠(yuǎn)還沒有結(jié)束。

JS 調(diào)用 OCX(CAB)

引入 OCX 控件

新建一個 HTML 文件,我們通過如下方式引入 OCX:

一項一項解釋:

id="xpButton" 表示此 object 對象的 id 為 xpButton,命名隨便都可以,后續(xù)會用到。

classid="clsid:134EE1CC-4B8A-4E74-8C41-F4990065E2E1"?看到這個,應(yīng)該很熟悉。classid="clsid:這部分照抄,不要改動。只改動冒號 : 后面部分就行了。(本人不小心把 clsid: 這一部分漏掉了,寫成了 classid="134EE1CC-4B8A-4E74-8C41-F4990065E2E1",結(jié)果 CAB 文件下載不下來)。注意:千萬別漏了 clsid。

codebase="./xpbutton.cab#version=1,0,0,1" 這一部分代碼是告訴瀏覽器,如果找不到 clsid 為?134EE1CC-4B8A-4E74-8C41-F4990065E2E1 注冊表,也就是系統(tǒng)中沒有注冊過此 xpbutton.ocx ,則去找對應(yīng)的 xpbutton.cab 文件。這里 "./xpbutton.cab" 意思是和當(dāng)前 html 存放在同一目錄下的 xpbutton.cab 文件?!?/”表示當(dāng)前路徑,也就是 html 所在的路徑。后面的 "#version=1,0,0,1" 表示當(dāng)前 OCX 的版本號,也就是 CAB 壓縮包中 INF 文件里面寫的 OCX 的版本號(FileVersion)。注意版本號:1,0,0,1 是用逗號 "," 分隔,不是點(diǎn)號 "." ,如果你用了點(diǎn)號 ".",那么恭喜你,你又錯了。

補(bǔ)充說明:我們遇到過三個版本號

1. OCX 編寫時,C++ 代碼中規(guī)定了 OCX 的版本號。

2. OCX 打包 CAB 文件時,INF 文件中規(guī)定了當(dāng)前 OCX 的版本號。

3. HTML 調(diào)用 OCX 時,CODEBASE 表明了需要調(diào)用的 OCX 版本號。

這三個版本號需要一致。

很有意思的是,如果想要升級?OCX,其實很簡單,讓 OCX 編寫人員升級 OCX,然后我們升級 INF 文件中的版本號,再把相應(yīng) HTML 中的版本號也升級。瀏覽器調(diào)用此 HTML 時候,如果發(fā)現(xiàn) CODEBASE 中的版本號升級了,則會自動重新下載 CAB 文件,并重新注冊。

之前,為了測試 OCX 升級后是否本身有問題,手動注冊此 OCX ,沒有重新打包 CAB,結(jié)果每次訪問都發(fā)現(xiàn)注冊的是 CAB 中上一個版本的 OCX。說明只要發(fā)現(xiàn)注冊過的 OCX 版本和 CAB 版本不一致的情況下,瀏覽器都會重新下載 CAB,并重新注冊。

這里還要說明一點(diǎn)就是,OCX 被編寫出來后。clsid 就固定了。此 OCX 不管注冊到哪臺電腦上,查看注冊表,clsid 都是一樣的,不會改變。這也就是為什么我們在 HTML 里面,直接可以寫上 clsid 的原因。因為客戶下載 CAB ,自動注冊后,OCX 的 clsid 就是我們編寫 C++ 時候規(guī)定的 clsid。

JS 調(diào)用 OCX 方法

解釋以上代碼

1.xpButton.AboutBox() ;

xpButton 其實不是憑空出現(xiàn)的,這里的 xpButton 是 標(biāo)簽的 id,大家看上面的截圖可以看到,……。

2. xpButton.AboutBox();

AboutBox() 其實是 OCX 中的一個方法。各位如果想要知道此 OCX 中有哪些方法,首選的是找 OCX 開發(fā)者,在找不到的情況下,通過 tstcon32 軟件,各位可以在這里下載:tstcon32 ActiveX 容器訪問密碼 904d。如果不能使用,根據(jù)報錯提示下載相應(yīng) DLL 即可。(研究 OCX 留下的后遺癥,總覺得某些軟件會缺少 DLL )

3. 為什么要 try catch

OCX 的繁瑣和摸不著頭腦,很重要的原因是,即使調(diào)用失敗它也不會報錯。所以,我們必須要在這里 try catch 手動彈出錯誤信息。但問題其實也沒有那么簡單,即使是有報錯信息,提示也讓人摸不到頭腦。

注意,各位一定要記得 try catch,不然任何錯誤都不會有提示。

下面總結(jié)一下本人遇到的報錯信息與真實原因的對應(yīng)關(guān)系,以防止各位各種百度、Google 最后找到的是錯誤的解決方案。

OCX 報錯,一般情況下,都是本機(jī)測試通過后,部署到服務(wù)器或者使用其他人的電腦,發(fā)現(xiàn)調(diào)用失敗。

1.[object Error]、Error:找不到成員

如果是遇到上面的報錯:[object Error] 、Error:找不到成員

1.首先確定C:\Windows\ocx?目錄下是否有下載的 OCX 文件(如果各位下載了本教程中的 INF 文件,則到C:\Windows\ocx?目錄下去找),如果該目錄下沒有任何文件或者沒有該目錄,則就對照上文,查看是否是 INF 文件編寫有問題,或者是 HTML 引入 OCX 對象有錯誤,導(dǎo)致下載失敗。

2.如果?OCX?文件已下載,則表示雖然 CAB 文件沒問題,但 OCX 未注冊或者說是注冊失敗。注冊失敗的原因,我們首先需要確認(rèn)是否是缺少 DLL 。如何確認(rèn),可以使用上文提到的Dependency Walker軟件。如果發(fā)現(xiàn)確實是少了 DLL,那我們應(yīng)該重新打包 CAB,將所缺少的 DLL 文件一起打包到 CAB 中。很多時候,我們通過 CAB 自動注冊 OCX ,大多數(shù)情況下是不會報任何的錯誤的。即使是因為缺少 DLL 沒有注冊成功,也沒有任何提示。本人在很多電腦上測試的結(jié)果是,只有一臺 Win7,出現(xiàn)了缺少 DLL 的報錯示,其他所有電腦都沒有任何的錯誤提示。這里特別需要注意:打包 CAB 文件后,請用多臺電腦進(jìn)行測試,最好測試不同的系統(tǒng),也盡量可以挑選公司非開發(fā)人員的電腦。千萬別在自己電腦上測試通過,或者某些 OCX 開發(fā)者電腦上測試通過后便認(rèn)為其沒有問題。

2. 對象不支持此屬性或方法

這個錯誤,在開發(fā)的過程中,是必然會遇到的。剛開始,一直以為是調(diào)用方式有問題,在嘗試了網(wǎng)上能找到的所有其他不同調(diào)用方式后發(fā)現(xiàn),并非如此。如果能保證 OCX 的正確性的前提下,此問題的根本原因是因為瀏覽器對于 OCX 不信任,攔截了 OCX 里面的方法調(diào)用。解決此問題的根本辦法是修改瀏覽器設(shè)置。

3.修改瀏覽器安全設(shè)置

網(wǎng)上可以找到很多瀏覽器的修改點(diǎn),其實大部分不需要修改,修改了反而降低了安全性,增加風(fēng)險。

反選“對該區(qū)域中的所有站點(diǎn)要求服務(wù)器驗證(https)”,填上服務(wù)器地址,例如:http://192.168.0.61 然后添加,添加完成后,再次勾選"對該區(qū)域中的所有站點(diǎn)要求服務(wù)器驗證(https)"。這一步的操作是保證瀏覽器信任此站點(diǎn)。

此處修改信任站點(diǎn)的安全性級別,將圖上的兩個,由原來的禁止,修改為提示或者啟用。

其實在首次訪問 CAB 網(wǎng)頁前,我們就應(yīng)該先修改瀏覽器安全性策略,修改完成后再訪問,一般都不會出現(xiàn)什么問題。

至此,OCX?的相關(guān)知識已經(jīng)全部介紹完畢,此教程應(yīng)該可以幫助大家少走一些彎路。這也是最近兩個星期的研究成果。

2015.08.26?補(bǔ)充

1.注意:如果使用了?Java?開發(fā),后臺使用了?Spring。則應(yīng)該在 Web.xml?中添加下面的代碼。

[html]view plaincopy

default

*.cab

上面代碼告訴?Spring?不要攔截 *.cab?靜態(tài)文件。

2.JSP?引入?CAB?文件

[html]view plaincopy

classid="clsid:F6F2B22E-FC89-489F-967B-9676EB269F55"

CODEBASE="${pageContext.request.contextPath}/cab/readcard.cab#version=1,0,0,1"

>

在工程中引入?CAB?文件,我們需要寫

[html]view plaincopy

CODEBASE="${pageContext.request.contextPath}/cab/readcard.cab#version=1,0,0,1"

${pageContext.request.contextPath}?表示工程名

cab?文件存放在?webapp/cab?下面

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,545評論 19 139
  • 一、溫故而知新 1. 內(nèi)存不夠怎么辦 內(nèi)存簡單分配策略的問題地址空間不隔離內(nèi)存使用效率低程序運(yùn)行的地址不確定 關(guān)于...
    SeanCST閱讀 8,120評論 0 27
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 47,268評論 6 342
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,983評論 25 709
  • 加入合金元素使相圖的E點(diǎn)左移,出現(xiàn)了含碳量低于2.11%的合金鋼中出現(xiàn)萊氏體,這種合金就成為萊氏體鋼。
    孔李聃丘閱讀 1,473評論 0 1

友情鏈接更多精彩內(nèi)容