MFC ActiveX打包CAB
- 準備打包簽名工具和要打包的檔案
将需要簽名和打包的 OCX 、dll和指令放到相同檔案夾。
-
制作簽名證書
在指令行運作下面指令:
makecert.exe -ss reader -n “CN=****” -sv reader.pvk -r reader.cer
輸入三次,密碼,檢視控制台出現 Succeeded 表示成功。
此時生成檔案:reader.cer和reader.pvk
-
運作指令:
cert2spc.exe reader.cer reader.spc
檢視控制台,出現 Succeeded 表示成功。
此時會生成檔案:reader.spc
兩條指令結束,我們一共得到三個檔案:reader.cer、reader.pvk、reader.spc
3. 對 OCX 進行簽名
打包 CAB 之前,首先需要對 OCX 本身進行簽名操作,這一步很重要,如果沒做,你可能就犯錯了。
輕按兩下打開signcode.exe
選擇簽名的ocx
下一步
下一步
下一步
下一步
-
編寫inf檔案
INF 檔案也是一個重點,如果編寫錯誤,則不能正确打包。(各位可以拷貝本人編寫的 INF 檔案,在此基礎上進行修改,保證 INF 檔案的正确性)
如果打包 CAB 沒有問題 ocx 、dll 都會下載下傳到 c:/windows/reader/ 目錄下,友善各位解除安裝 ocx ,删除 dll 檔案
[version]
signature=" C H I C A G O CHICAGO CHICAGO"
AdvancedINF=2.0
[DefaultInstall]
CopyFiles=files
RegisterOCXs=RegisterFiles
[DefaultUninstall]
cleanup=1
Delfiles=files
UnRegisterOCXs=RegisterFiles
[SourceDisksNames]
1=%DiskName%,“reader.cab”,1
[SourceDisksFiles]
CardReaderActiveX.ocx=1
BK_Reader_Library.dll=1
IC_Reader_Library.dll=1
ID_Reader_Library.dll=1
dcrf32.dll=1
devcomm.dll=1
iccinterface.dll=1
msvcr100.dll=1
RdCard.dll=1
sdtapi.dll=1
SS728M05_SDK.dll=1
WebP.dll=1
WltRS.dll=1
[RegisterFiles]
%30%\Windows\reader\CardReaderActiveX.ocx
[DestinationDirs]
files=30,Windows\reader
[files]
CardReaderActiveX.ocx=CardReaderActiveX.ocx
BK_Reader_Library.dll=BK_Reader_Library.dll
IC_Reader_Library.dll=IC_Reader_Library.dll
ID_Reader_Library.dll=ID_Reader_Library.dll
dcrf32.dll=dcrf32.dll
devcomm.dll=devcomm.dll
iccinterface.dll=iccinterface.dll
msvcr100.dll=msvcr100.dll
RdCard.dll=RdCard.dll
sdtapi.dll=sdtapi.dll
SS728M05_SDK.dll=SS728M05_SDK.dll
WebP.dll=WebP.dll
WltRS.dll=WltRS.dll
[CardReaderActiveX.ocx]
file-win32-x86=thiscab
clsid={99E3D0E6-CE7E-4424-9599-2AE3DFB32808}
FileVersion=1,0,0,0
RegisterServer=yes
[iBK_Reader_Library.dll]
file=thiscab
FileVersion=1,0,0,1
[IC_Reader_Library.dll]
file=thiscab
FileVersion=1,0,0,1
[ID_Reader_Library.dll]
file=thiscab
FileVersion=1,0,0,1
[dcrf32.dll]
file=thiscab
FileVersion=8,0,1,7
[devcomm.dll]
file=thiscab
FileVersion=1,0,0,1
[iccinterface.dll]
file=thiscab
FileVersion=1,1,0,1
[msvcr100.dll]
file=thiscab
FileVersion=10,0,30319,415
[RdCard.dll]
file=thiscab
FileVersion=2,6,2,0
[sdtapi.dll]
file=thiscab
FileVersion=2,0,2,0
[SS728M05_SDK.dll]
file=thiscab
FileVersion=1,6,0,7
[WebP.dll]
file=thiscab
FileVersion=1,0,0,109
[WltRS.dll]
file=thiscab
FileVersion=1,0,0,1
[Strings]
DiskName=“Windows\reader”
-
OCX 打包 CAB 檔案
運作指令:
CABARC.EXE -s 6144 n reader.cab CardReaderActiveX.ocx BK_Reader_Library.dll ID_Reader_Library.dll IC_Reader_Library.dll dcrf32.dll devcomm.dll iccinterface.dll msvcr100.dll RdCard.dll sdtapi.dll SS728M05_SDK.dll WebP.dll WltRS.dll reader.inf
需要解釋一下這條指令:是将 CardReaderActiveX.ocx 、reader.inf、其他dll 檔案打包成reader.cab 檔案
-
對 CAB 檔案簽名
對 CAB 檔案簽名的過程,可以檢視上文對 OCX 檔案簽名的過程,除了第一步此處選擇的是 CAB 檔案之外。其餘步驟完全相同。到目前為止,我們已經将 OCX 打包成 CAB 。
-
JS 調用 OCX(CAB)
① 建立一個 HTML 檔案,我們通過如下方式引入 OCX:
② JSP 引入 CAB 檔案,codebase需要改為對應的cab所在伺服器的路徑
classid=“clsid:F6F2B22E-FC89-489F-967B-9676EB269F55”
CODEBASE="${pageContext.request.contextPath}/cab/readcard.cab#version=1,0,0,1"
一項一項解釋:
id=“reader” 表示此 object 對象的 id 為 reader,命名随便都可以,後續會用到。
classid=“clsid:99E3D0E6-CE7E-4424-9599-2AE3DFB32808” 看到這個,應該很熟悉。classid="clsid:這部分照抄,不要改動。隻改動冒号 : 後面部分就行了。
codebase=“reader.cab#Version=1,0,0,0” 這一部分代碼是告訴浏覽器,如果找不到 clsid 為 99E3D0E6-CE7E-4424-9599-2AE3DFB32808 系統資料庫,也就是系統中沒有注冊過此 CardReaderActiveX.ocx ,則去找對應的 reader.cab 檔案。這裡 “./reader.cab” 意思是和目前 html 存放在同一目錄下的 reader.cab 檔案。“./”表示目前路徑,也就是 html 所在的路徑。後面的 “#version=1,0,0,1” 表示目前 OCX 的版本号,也就是 CAB 壓縮包中 INF 檔案裡面寫的 OCX 的版本号(FileVersion)。注意版本号:1,0,0,1 是用逗号 “,” 分隔,不是點号 “.” ,如果你用了點号 “.”,那麼恭喜你,你又錯了。
補充說明:我們遇到過三個版本号
- OCX 編寫時,C++ 代碼中規定了 OCX 的版本号。
- OCX 打包 CAB 檔案時,INF 檔案中規定了目前 OCX 的版本号。
-
HTML 調用 OCX 時,CODEBASE 表明了需要調用的 OCX 版本号。
這三個版本号需要一緻。
很有意思的是,如果想要更新 OCX,其實很簡單,讓 OCX 編寫人員更新 OCX,然後我們更新 INF 檔案中的版本号,再把相應 HTML 中的版本号也更新。浏覽器調用此 HTML 時候,如果發現 CODEBASE 中的版本号更新了,則會自動重新下載下傳 CAB 檔案,并重新注冊。
之前,為了測試 OCX 更新後是否本身有問題,手動注冊此 OCX ,沒有重新打包 CAB,結果每次通路都發現注冊的是 CAB 中上一個版本的 OCX。說明隻要發現注冊過的 OCX 版本和 CAB 版本不一緻的情況下,浏覽器都會重新下載下傳 CAB,并重新注冊。
這裡還要說明一點就是,OCX 被編寫出來後。clsid 就固定了。此 OCX 不管注冊到哪台電腦上,檢視系統資料庫,clsid 都是一樣的,不會改變。這也就是為什麼我們在 HTML 裡面,直接可以寫上 clsid 的原因。因為客戶下載下傳 CAB ,自動注冊後,OCX 的 clsid 就是我們編寫 C++ 時候規定的 clsid。
JS 調用 OCX 方法
調用每個方法或屬性時,最好添加try…catch
-
常見錯誤
[object Error]、Error:找不到成員
如果是遇到上面的報錯:[object Error] 、Error:找不到成員
1.首先确定C:\Windows\reader 目錄下是否有下載下傳的 OCX 檔案,如果該目錄下沒有任何檔案或者沒有該目錄,則就對照上文,檢視是否是 INF 檔案編寫有問題,或者是 HTML 引入 OCX 對象有錯誤,導緻下載下傳失敗。
2.如果 OCX 檔案已下載下傳,則表示雖然 CAB 檔案沒問題,但 OCX 未注冊或者說是注冊失敗。注冊失敗的原因,我們首先需要确認是否是缺少 DLL 。如何确認,可以使用上文提到的Dependency Walker軟體。如果發現确實是少了 DLL,那我們應該重新打包 CAB,将所缺少的 DLL 檔案一起打包到 CAB 中。很多時候,我們通過 CAB 自動注冊 OCX ,大多數情況下是不會報任何的錯誤的。即使是因為缺少 DLL 沒有注冊成功,也沒有任何提示。本人在很多電腦上測試的結果是,隻有一台 Win7,出現了缺少 DLL 的報錯示,其他所有電腦都沒有任何的錯誤提示。這裡特别需要注意:打包 CAB 檔案後,請用多台電腦進行測試,最好測試不同的系統,也盡量可以挑選公司非開發人員的電腦。千萬别在自己電腦上測試通過,或者某些 OCX 開發者電腦上測試通過後便認為其沒有問題。
對象不支援此屬性或方法
這個錯誤,在開發的過程中,是必然會遇到的。剛開始,一直以為是調用方式有問題,在嘗試了網上能找到的所有其他不同調用方式後發現,并非如此。如果能保證 OCX 的正确性的前提下,此問題的根本原因是因為浏覽器對于 OCX 不信任,攔截了 OCX 裡面的方法調用。解決此問題的根本辦法是修改浏覽器設定。
修改浏覽器安全設定
啟用相關的activex選項