- 浏览: 51186 次
- 性别:
- 来自: 深圳
最新评论
-
webiis2008:
尝试了很久用自己做的证书被浏览器拦截了。最后购买沃通的代码签名 ...
VC++开发Activex控件以及签名发布 -
freeubuntu-it:
我按照demo做的时候,出现提示对话框“是否允许运行软件,如A ...
VC++开发Activex控件以及签名发布 -
jwsong2001ok:
我照着做的demo运行时,IE中就会提示,“在此页上的Acti ...
VC++开发Activex控件以及签名发布 -
sjxinrui:
挺好,=-= 加油
Compass全文检索系列之一:Compass入门 -
aa00aa00:
这个例子不错,谢谢了
Compass全文检索系列之一:Compass入门
前言
本人不懂C++,当前由于要做一个打印控件,使用Activex插件技术,所以在网络上搜索了相关技术文档,今天有空,遂将自己的当前学到的一些关于Activex技术整理之,进而和朋友们分享之。
一、 开发环境
开发工具:Visual Studio 2008
开发语言:Visual C++
测试工具:IE 7+
二、 创建MFC ActiveX项目
1、 打开VS2008新建MFC项目。这里我们取名为“PrintUtil”。
2、 输入项目名称为“PrintUtil”和项目位置。点击“确定”按钮,打开向导对话框。
3、 选择“控件设置”选项卡,具体设置可参考上图。其它选项卡为默认设置。最后点击“完成”按钮保存设置。
三、 添加控件方法
VC2005会为我们自动创建好MFC ActiveX程序框架,我们只要给该ActiveX控件添加方法即可。现在我们给控件添加一个“AddFun”方法,这个方法是将两个数相加并返回结果。
1、 点击“视图”,打开“类视图”窗口。
2、 展开“PrintUtilLib”项,选中“_DPrintUtil”项。点击鼠标右键,选择“添加”下的“添加方法”。
3、 打开添加方法向导窗口。因为我们是添加一个加法方法,所以我们设置的返回类型为LONG型,方法名设为AddFun,添加两个LONG类型参数Add1,Add2。
4、 其它为默认设置,点击“完成”按钮完成添加方法。接下来我们打开“解决方案资源管理器”打开“PrintUtilCtrl.cpp”文件。
5、 打开代码视图,我们会发现VC2005已经为我们添加了一个“AddFun”方法,我们在方法内添加“return Add1 + Add2;”语句。
四、 MFC Activex 安全问题
1、在默认环境下,编译的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文件中实现以下方法:
// 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; }
现在控件就可以在自注册时就注册为安全控件了。
2、设置项目属性 将配置类型设置成静态库(.lib)
3、最后生成项目,ocx控件就产生了。
五、 ActiveX发布步骤
在这里简单说明下,打包activeX需要制作证书,具体用到makecert 、cert2spc 、signtool 这三个VS提供的工具,工具在VS文件夹里面,以下制作过程需要在工具所在的文件夹下完成!
1、单击"开始"-->"运行(R)"-->输入"cmd"-->回车-->进入到操作的控件所在的目录(需要将上面所说的工具,和ocx控件放到一个文件夹下);
2、创建PVK文件(私人密匙文件),在命令行中输入" makecert -sk PrintUtil PrintUtil.pvk -n CN=XXXXXXX公司",然后回车;
sk-表示主题的密钥容器位置,ss-主题的证书存储名称, n-证书颁发对象,r-证书存储位置;
3、创建CER文件(公司证书),在命令行中输入" makecert -sk PrintUtil.pvk PrintUtil.cer ",然后回车,如图所示,若出现"Successed"提示,则会在C:\ PrintUtil目录下生成PrintUtil.cer文件;
sk-表示主题的密钥容器位置,is-颁发者的证书存储名称, n-证书颁发对象,ic-颁发者的证书存储位置,-$-授权范围(用于代码签名);
4、创建SPC测试软件出版商证明书,在命令行中输入" cert2spc PrintUtil.cer PrintUtil.spc ",然后回车;
5、创建INF文件,用记录本编辑以下信息:
[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
6、创建CAB文件,在命令行中输入" cabarc -s 6144 n PrintUtil.cab PrintUtil.ocx PrintUtil.inf ",-s 选项表示在压缩文件中保留用于代码签名的空间,n命令指定希望创建 CAB 文件,然后回车;
7、使用Code Signing Wizard签署一个CAB文件,首先双击运行工具集里面的signcode.exe(或在命令行里直接输入“signcode”后回车),系统会弹出如图所示的数字签名向导;
8、单击"下一步(N)"按钮,选择要进行数字签名的且已做成CAB包的文件PrintUtil.cab文件;
9、选择好CAB包后单击"下一步(N)"按钮,在选择想要的签名类型里选择"自定义(C)"并单击"下一步(N)"按钮;
10、点击“从文件选择”签名证书 ( 公钥文件 ),如: PrintUtil.cer :
11、在图20中单击“下一步(N)”按钮来到下图,然后在图里选择“CSP中的私钥(K)”。
12、在上图中单击“下一步(N)”按钮,然后在下图中的散列算法中选择“shal”,并单击“下一步(N)”按钮。
13、在“证书路径中的证书”中选择“证书路径中的所有证书,包括根证书(C)”,在“其它证书(可选)”中选择“包括在以下PKCS #7 证书(.p7b)文件中的证书(P):”,并单击“浏览(R)…”按钮选择PrintUtil.spc文件,选择完后单击“下一步(N)”按钮:
14、接下来在弹出的“数据描述”窗口中输入公司的名称和网址并单击“下一步(N)”按:
15、现大部份工作都已完成,在接下来的一步当中是可选的操作,其作用只是为CAB加入时间戳,此步骤完全可以不做。
VeriSign: http://timestamp.verisign.com/scripts/timstamp.dll
Comodo: http://timestamp.comodoca.com/authenticode
GeoTrust/TrustCenter: http://www.trustcenter.de/codesigning/timestamp
16、完成
六、 运行
编写jsp页面,test.jsp
<%@ 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>
运行结果:
好了,今天就写到这里了,如果朋友们有什么疑问或者更好的建议和意见,请Email Me。
Email:df.jxnu@gmail.com
本文所用到的工具见附件:
转载请声明本文链接
- makeCAB.rar (188.6 KB)
- 下载次数: 412
评论
“是否允许运行软件,如ActiveX控件和插件”~
不需要,C++语言实现的,这里和dotnet无关
发表评论
-
【设计模式笔录】—单例模式剖析(一)
2011-02-25 11:38 921在软件系统中,经常有这样一些类,必须保证它们在系 ... -
quartz corn表达式
2011-01-14 09:47 1421一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素 ... -
解决PowerDesigner中Name与Code同步的问题。
2010-05-13 15:33 995PowerDesigner中,但修改了某个字段的name,其c ... -
JQuery系列(一)入门
2010-04-23 13:30 885Jquery强调的理念是写得少,做的多(Wirte le ... -
DOS 命令删除文件夹下所有子文件夹和文件
2010-04-22 21:40 5114for /d %%i in ({folder}\*) do ... -
网页变灰方法
2010-04-21 09:23 1093大家都看到了,各大网站都已经将自己的主页甚至全部也面进 ...
相关推荐
VC++开发Activex控件以及签名发布.pdf ACTIVEX编程开发总结
[001]VC++编写ActiveX控件详解.zip上位机开发VC串口学习资料源码下载[001]VC++编写ActiveX控件详解.zip上位机开发VC串口学习资料源码下载[001]VC++编写ActiveX控件详解.zip上位机开发VC串口学习资料源码下载[001]...
VC++编写ActiveX控件
VC 开发Activex控件以及签名发布技术
如何使用VC++ 2005 给ActiveX控件添加方法,属性,事件如何使用VC++ 2005 给ActiveX控件添加方法,属性,事件如何使用VC++ 2005 给ActiveX控件添加方法,属性,事件如何使用VC++ 2005 给ActiveX控件添加方法,属性,事件如何...
本论文描写VC++在activex控件的动画编程.
在VC++中用ActiveX控件实现与单片机的串行通信
VC++编写ActiveX控件和CSharp调用activeX[整理].pdf
VC++6.0写ActiveX控件,和WEB通信的一些心得
NULL 博文链接:https://becomebetter.iteye.com/blog/2201118
activex控件的vc++编程,可以直接用,也可以用来学习。
使用C_开发ActiveX控件使用C_开发ActiveX控件使用C_开发ActiveX控件
VC++ActiveX控件应用实例——Clock和MyATLWin工程源代码.rar
Activex\C#开发ActiveX控件,.NET开发OCX控件案例
01_MyActiveX1 是用VC做的一个最简单的Activex插件 02_MyActiveX2 使用VC做的一个三角函数曲线Activex插件 03_ActiveXInDlg 在应用程序中调用示例2中的插件 04_ActiveXInWeb 在Web程序,即html网页中调用示例2中的...
C# 开发Activex控件 C# 开发Activex控件 C# 开发Activex控件
ActiveX控件签名工具,进行对OCX及DLL控件进行签名操作处理