前言
本人不懂C++,當前因爲要作一個打印控件,使用Activex插件技術,因此在網絡上搜索了相關技術文檔,今天有空,遂將本身的當前學到的一些關於Activex技術整理之,進而和朋友們分享之。
1、 開發環境
開發工具:Visual Studio 2008
開發語言:Visual C++javascript
測試工具:IE 7+
2、 建立MFC ActiveX項目
一、 打開VS2008新建MFC項目。這裏咱們取名爲「PrintUtil」。html
![](http://static.javashuo.com/static/loading.gif)
二、 輸入項目名稱爲「PrintUtil」和項目位置。點擊「肯定」按鈕,打開向導對話框。 java
![](http://static.javashuo.com/static/loading.gif)
三、 選擇「控件設置」選項卡,具體設置可參考上圖。其它選項卡爲默認設置。最後點擊「完成」按鈕保存設置。算法
3、 添加控件方法
VC2005會爲咱們自動建立好MFC ActiveX程序框架,咱們只要給該ActiveX控件添加方法便可。如今咱們給控件添加一個「AddFun」方法,這個方法是將兩個數相加並返回結果。
一、 點擊「視圖」,打開「類視圖」窗口。
![](http://static.javashuo.com/static/loading.gif)
二、 展開「PrintUtilLib」項,選中「_DPrintUtil」項。點擊鼠標右鍵,選擇「添加」下的「添加方法」。
![](http://static.javashuo.com/static/loading.gif)
三、 打開添加方法嚮導窗口。由於咱們是添加一個加法方法,因此咱們設置的返回類型爲LONG型,方法名設爲AddFun,添加兩個LONG類型參數Add1,Add2。
![](http://static.javashuo.com/static/loading.gif)
四、 其它爲默認設置,點擊「完成」按鈕完成添加方法。接下來咱們打開「解決方案資源管理器」打開「PrintUtilCtrl.cpp」文件。安全
![](http://static.javashuo.com/static/loading.gif)
五、 打開代碼視圖,咱們會發現VC2005已經爲咱們添加了一個「AddFun」方法,咱們在方法內添加「return Add1 + Add2;」語句。網絡
![](http://static.javashuo.com/static/loading.gif)
4、 MFC Activex 安全問題
一、在默認環境下,編譯的MFC Activex控件,只能在本地代碼中運行,即在http://localhost/xxx/xxx.htm中執行,而在http://127.0.0.1/xxx/xxx.htm中提示無相關屬性,須要設置其初始化和腳本運行的安全性
ActiveX在遠程IE頁面上執行,須要實現安全接口。
在ATL寫的ActiveX中,用IObjectSafety。
http://support.microsoft.com/kb/168371/en-us
在MFC寫的ActiveX中,直接修改註冊表。
http://support.microsoft.com/kb/161873/en-us
mfc實現的ocx,要在app實現文件中包括兩個文件:
在PrintUtil.h文件中實現如下方法:app
Cpp代碼 框架
![收藏代碼](http://static.javashuo.com/static/loading.gif)
- // PrintUtil.cpp : CPrintUtilApp 和DLL 註冊的實現。
- #include "stdafx.h"
- #include "PrintUtil.h"
- #include <objsafe.h>
-
- #ifdef _DEBUG
- #define new DEBUG_NEW
- #endif
-
-
- CPrintUtilApp theApp;
-
- const GUID CDECL BASED_CODE _tlid =
- { 0x3C8F86CA, 0x6470, 0x4B7C, { 0xB2, 0x76, 0x3B, 0xEB, 0xF, 0xB0, 0x1B, 0x4E } };
- const WORD _wVerMajor = 1;
- const WORD _wVerMinor = 0;
-
-
-
- // CPrintUtilApp::InitInstance - DLL 初始化
-
- BOOL CPrintUtilApp::InitInstance()
- {
- BOOL bInit = COleControlModule::InitInstance();
-
- if (bInit)
- {
- // TODO: 在此添加您本身的模塊初始化代碼。
- }
-
- return bInit;
- }
-
-
-
- // CPrintUtilApp::ExitInstance - DLL 終止
-
- int CPrintUtilApp::ExitInstance()
- {
- // TODO: 在此添加您本身的模塊終止代碼。
-
- return COleControlModule::ExitInstance();
- }
-
- // 建立組件種類
- HRESULT CreateComponentCategory(CATID catid, WCHAR* catDescription)
- {
- ICatRegister* pcr = NULL ;
- HRESULT hr = S_OK ;
- hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
- if (FAILED(hr)) return hr;
- // Make sure the HKCR\Component Categories\{..catid...}
- // key is registered.
- CATEGORYINFO catinfo;
- catinfo.catid = catid;
- catinfo.lcid = 0x0409 ; // english
- // Make sure the provided description is not too long.
- // Only copy the first 127 characters if it is.
- int len = wcslen(catDescription);
- if (len>127) len = 127;
- wcsncpy(catinfo.szDescription, catDescription, len);
- // Make sure the description is null terminated.
- catinfo.szDescription[len] = '\0';
- hr = pcr->RegisterCategories(1, &catinfo);
- pcr->Release();
- return hr;
- }
-
- // 註冊組件種類
- HRESULT RegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
- {
- // Register your component categories information.
- ICatRegister* pcr = NULL ;
- HRESULT hr = S_OK ;
- hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr, NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
- if (SUCCEEDED(hr)) {
- // Register this category as being "implemented" by the class.
- CATID rgcatid[1];
- rgcatid[0] = catid;
- hr = pcr->RegisterClassImplCategories(clsid, 1, rgcatid);
- }
- if (pcr != NULL) pcr->Release();
- return hr;
- }
-
- // 卸載組件種類
- HRESULT UnRegisterCLSIDInCategory(REFCLSID clsid, CATID catid)
- {
- ICatRegister* pcr = NULL ;
- HRESULT hr = S_OK ;
- hr = CoCreateInstance(CLSID_StdComponentCategoriesMgr,
- NULL, CLSCTX_INPROC_SERVER, IID_ICatRegister, (void**)&pcr);
- if (SUCCEEDED(hr)) {
- // Unregister this category as being "implemented" by the class.
- CATID rgcatid[1] ;
- rgcatid[0] = catid;
- hr = pcr->UnRegisterClassImplCategories(clsid, 1, rgcatid);
- }
- if (pcr != NULL) pcr->Release();
- return hr;
- }
-
-
- // DllRegisterServer - 將項添加到系統註冊表
- STDAPI DllRegisterServer(void)
- {
- HRESULT hr;
- AFX_MANAGE_STATE(_afxModuleAddrThis);
- if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), _tlid))
- return ResultFromScode(SELFREG_E_TYPELIB);
- if (!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
- return ResultFromScode(SELFREG_E_CLASS);
- // 標記控件初始化安全.
- // 建立初始化安全組件種類
- hr = CreateComponentCategory(CATID_SafeForInitializing, L"Controls safely initializable from persistent data!");
- if (FAILED(hr)) return hr;
- // 註冊初始化安全
- hr = RegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForInitializing);
- if (FAILED(hr)) return hr;
- // 標記控件腳本安全
- // 建立腳本安全組件種類
- hr = CreateComponentCategory(CATID_SafeForScripting, L"Controls safely scriptable!");
- if (FAILED(hr)) return hr;
- // 註冊腳本安全組件種類
- hr = RegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForScripting);
- if (FAILED(hr)) return hr;
- return NOERROR;
- }
-
- // DllUnregisterServer - Removes entries from the system registry
- STDAPI DllUnregisterServer(void)
- {
- HRESULT hr;
- AFX_MANAGE_STATE(_afxModuleAddrThis);
- if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
- return ResultFromScode(SELFREG_E_TYPELIB);
- if (!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
- return ResultFromScode(SELFREG_E_CLASS);
- // 刪除控件初始化安全入口.
- hr=UnRegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForInitializing);
- if (FAILED(hr)) return hr;
- // 刪除控件腳本安全入口
- hr=UnRegisterCLSIDInCategory(BASED_CODE _tlid , CATID_SafeForScripting);
- if (FAILED(hr)) return hr;
- return NOERROR;
- }
如今控件就能夠在自注冊時就註冊爲安全控件了。
二、設置項目屬性 將配置類型設置成靜態庫(.lib)
![](http://static.javashuo.com/static/loading.gif)
三、最後生成項目,ocx控件就產生了。
5、 ActiveX發佈步驟
在這裏簡單說明下,打包activeX須要製做證書,具體用到makecert 、cert2spc 、signtool 這三個VS提供的工具,工具在VS文件夾裏面,如下製做過程須要在工具所在的文件夾下完成!
一、單擊"開始"-->"運行(R)"-->輸入"cmd"-->回車-->進入到操做的控件所在的目錄(須要將上面所說的工具,和ocx控件放到一個文件夾下);jsp
二、建立PVK文件(私人密匙文件),在命令行中輸入" makecert -sk PrintUtil PrintUtil.pvk -n CN=XXXXXXX公司",而後回車;
sk-表示主題的密鑰容器位置,ss-主題的證書存儲名稱, n-證書頒發對象,r-證書存儲位置;
![](http://static.javashuo.com/static/loading.gif)
三、建立CER文件(公司證書),在命令行中輸入" makecert -sk PrintUtil.pvk PrintUtil.cer ",而後回車,如圖所示,若出現"Successed"提示,則會在C:\ PrintUtil目錄下生成PrintUtil.cer文件;
sk-表示主題的密鑰容器位置,is-頒發者的證書存儲名稱, n-證書頒發對象,ic-頒發者的證書存儲位置,-$-受權範圍(用於代碼簽名);ide
![](http://static.javashuo.com/static/loading.gif)
四、建立SPC測試軟件出版商證實書,在命令行中輸入" cert2spc PrintUtil.cer PrintUtil.spc ",而後回車;
![](http://static.javashuo.com/static/loading.gif)
五、建立INF文件,用記錄本編輯如下信息:
Inf代碼
![收藏代碼](http://static.javashuo.com/static/loading.gif)
- [version]
- signature="$CHINA$"
- AdvancedINF=1.0
-
- [Add.Code]
- PrintUtil.ocx=PrintUtil.ocx
-
- [PrintUtil.ocx]
- file=thiscab
- clsid={ 1BABEDC3-3936-4850-B79B-2417E28A5655 }
- FileVersion=1,0,0,0
- RegisterServer=yes
- DestDir=11
六、建立CAB文件,在命令行中輸入" cabarc -s 6144 n PrintUtil.cab PrintUtil.ocx PrintUtil.inf ",-s 選項表示在壓縮文件中保留用於代碼簽名的空間,n命令指定但願建立 CAB 文件,而後回車;
![](http://static.javashuo.com/static/loading.gif)
七、使用Code Signing Wizard簽署一個CAB文件,首先雙擊運行工具集裏面的signcode.exe(或在命令行裏直接輸入「signcode」後回車),系統會彈出如圖所示的數字簽名嚮導;
![](http://static.javashuo.com/static/loading.gif)
八、單擊"下一步(N)"按鈕,選擇要進行數字簽名的且已作成CAB包的文件PrintUtil.cab文件;
![](http://static.javashuo.com/static/loading.gif)
九、選擇好CAB包後單擊"下一步(N)"按鈕,在選擇想要的簽名類型裏選擇"自定義(C)"並單擊"下一步(N)"按鈕;
![](http://static.javashuo.com/static/loading.gif)
十、點擊「從文件選擇」簽名證書 ( 公鑰文件 ),如: PrintUtil.cer :
![](http://static.javashuo.com/static/loading.gif)
十一、在圖20中單擊「下一步(N)」按鈕來到下圖,而後在圖裏選擇「CSP中的私鑰(K)」。
![](http://static.javashuo.com/static/loading.gif)
十二、在上圖中單擊「下一步(N)」按鈕,而後在下圖中的散列算法中選擇「shal」,並單擊「下一步(N)」按鈕。
![](http://static.javashuo.com/static/loading.gif)
1三、在「證書路徑中的證書」中選擇「證書路徑中的全部證書,包括根證書(C)」,在「其它證書(可選)」中選擇「包括在如下PKCS #7 證書(.p7b)文件中的證書(P):」,並單擊「瀏覽(R)…」按鈕選擇PrintUtil.spc文件,選擇完後單擊「下一步(N)」按鈕:
![](http://static.javashuo.com/static/loading.gif)
1四、接下來在彈出的「數據描述」窗口中輸入公司的名稱和網址並單擊「下一步(N)」按:
![](http://static.javashuo.com/static/loading.gif)
1五、現大部份工做都已完成,在接下來的一步當中是可選的操做,其做用只是爲CAB加入時間戳,此步驟徹底能夠不作。
VeriSign: http://timestamp.verisign.com/scripts/timstamp.dll
Comodo: http://timestamp.comodoca.com/authenticode
GeoTrust/TrustCenter: http://www.trustcenter.de/codesigning/timestamp
1六、完成
![](http://static.javashuo.com/static/loading.gif)
6、 運行
編寫jsp頁面,test.jsp
Html代碼
![收藏代碼](http://static.javashuo.com/static/loading.gif)
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <%
- String path = request.getContextPath();
- String basePath = request.getScheme() + "://"
- + request.getServerName() + ":" + request.getServerPort()
- + path + "/";
- %>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <base href="<%=basePath%>">
-
- <title>My JSP 'index.jsp' starting page</title>
- <meta http-equiv="pragma" content="no-cache">
- <meta http-equiv="cache-control" content="no-cache">
- <meta http-equiv="expires" content="0">
- <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
- <meta http-equiv="description" content="This is my page">
- <object id="printUtil"
- classid="clsid:1BABEDC3-3936-4850-B79B-2417E28A5655"
- codebase="<%=basePath%>/PrintUtil.cab#version=1,0,0,0"></object>
- <script type="text/javascript">
- function add(arg1,args) {
- try {
- var v = printUtil.AddFun(arg1,args);
- alert(v);
- } catch (e) {
- alert(e.message)
- }
- }
- add(1,2);
- </script>
- </head>
- <body>
- </body>
- </html>
運行結果:
![](http://static.javashuo.com/static/loading.gif)
好了,今天就寫到這裏了,若是朋友們有什麼疑問或者更好的建議和意見,請Email Me。
讀完本篇能夠參考 【經常使用博客系列】中的ActiveX 中相關的系列文章,詳細深刻學習
原文連接有相關的工具 makeCAB.rar 下載項。