MFC Activex 开发、ocx打包成cab、部署、测试、自动升级
小小抱怨下:也许是MFC现在用的人少的缘故。在国内和国外都基本上找不到什么全的资料。特别是ocx打包成Cab时的安装文件inf的编写方面,国内基本上是copy,抄的还一知半解。查找个资源真心的累啊。现在将编写步骤和遇到的问题以及问题的解决办法记录下来。有的资源是参考了别人的博文,有引用的地方将附上连接,再次感谢这些博主,如有侵权,请联系本人,立即删除。
一、MFC Activex 项目的构建
此处使用的是:vs2015,操作按照图片顺序,没有特别注意的地方不做文字注释了。(不详细的地方可以参考:https://blog.csdn.net/longhuahaha/article/details/8556964)
第一:新建项目
activexdemo项目创建完成的目录结构
第二、先介绍四个文件
activexdemo.cpp、activexdemoCtrl.cpp、activexdemoPropPage.cpp、activexdemo.idl
(1) activexdemo.cpp文件中定义了DllRegisterServer和DllUnregisterServer,可以发现ActiveX的注册和反组册都与该类有关
(2)activexdemoCtrl.cpp文件
可以发现该头文件中声明了消息映射(让ActiveX控件程序可以接受系统发送的事件通知,如窗体创建和关闭事件),调度映射(让外部调用程序(包含ActiveX的容器)可以方便地访 问ActiveX控件的属性和方法),事件映射(让ActiveX控件可以向外部调用程序(包含ActiveX的容器)发送事件通知)。也就是说对ActiveX控件的窗口操作都将在这个类中完成,包括 ActiveX控件的创建,重绘,以及在此类中创建可视MFC窗体。
(3)activexdemoPropPage.cpp:显示ActiveX控件的属性页的
(4)activexdemo.idl:对外接口定义文件
第三、定义调度映射和事件映射方法,提供给外部调用者使用
(1)通过类视图进行定义:
在_Dactivexdemo上鼠标右键:
以添加对外接口方法BSTR initDvr(BSTR info, BSTR appKey, BSTR accessToken, LONG rowNum, FLOAT height);方法为例。BSTR为MFC中的数据类型。不懂的可以去百度了解。
点击下一步
填写完信息后点击完成,外部就可以调用方法initDvr,同时ActiveX控件项目代码的内部将会在三个文件中新增代码:
第四、Release生成ocx文件。并注册。
项目上右键->属性->常规->项目默认值->MFC的使用,设置为"在静态库中使用MFC",必须。如果不设置,在其他非开发环境电脑中会出现找不到DLL的错误。
在本地磁盘找到生成的activexdemo.ocx,此处路径为:E:\c++\activexdemo\Release。找到自己的项目地址中的Release文件夹。
注册activexdemo.ocx手动注册:
以管理员权限运行cmd(不会的百度)。
进入activexdemo.ocx的路径,使用regsvr32 xxx.ocx 对Activex进行注册。成功会弹出提示框。补充:regsvr32 xxx.ocx -u 对Activex控件进行反注册。
第五、Activex控件测试
(1)第一种方法:使用ActiveX Control Test Container。ActiveX Control Test Container工具下载。
将下载的控件解压后复制到安装的visual studio的安装根目录。
添加ActiveX Control Test Container到vs中。
添加完成再次点击工具菜单,点击开始测试:
给initDvr方法添加个MessageBox弹出信息:
找到activexdemoCtrl.cpp中的initDvr方法添加:
项目右键,点击重新生成,重新生成ocx文件。然后使用regsvr32 activedemo.ocx -u反注册下,再使用regsvr32 activedemo.ocx再次注册下。
此处可能会出现此种错误,可按照红色字体提示解决:
然后再次点击active container control,进行initDvr方法接口的测试。测试结果如下:
(2)html测试:使用<object></object>标签。在测试之前需要对activexdemo.ocx进行打包。此处打包成cab包。cab包需要下载cabarc.exe工具以及编写inf安装文件。cabarc.exe工具下载。
2.1 cabarc.exe下载之后建议将文件夹配置到系统环境(不懂的自己去百度,此处不再讨论)中。方便在其他文件夹中使用cabarc.exe命令。
2.2 对inf安装文件的编写。此为最重要。先以该项目为实例,之后会讲到子目录打包cab。
使用windwos自带的记事本建立一个inf文件。
打开activexdemo.inf文件进行编写:(inf的各节的详细解释请参考博文:https://www.cnblogs.com/xiangxinhouse/p/10392161.html)。
在桌面新建一个文件夹,命名为activedemo(名称自己定义)。将Release文件夹下的activexdemo.ocx,上面编写好的activexdemo.inf文件拷贝到新建的activedemo文件夹中。
打开一个新的cmd,进入到activedemo文件夹。进行cab打包。打包命令:cabarc -r -p N xxx.cab *。此命令为打包activedemo下的所有文件,包括子文件夹。
新建一个web项目。此处使用java web工程:
在webcontent(web)下新建一个files目录,并将打包好的cab文件复制到下面。并在index.jsp中添加<object></object>代码。注意version=1,0,0,0。1,0,0,0之间是,而不是.
详细如下:
发布web项目后测试。此处要设置IE浏览器允许未签名的activex控件进行安装和运行。不懂的百度。
测试结果如下:
此处讲下多个目录打包成cab的inf文件编写。假设activexdemo.ocx控件需要依赖test.dll和depends文件夹下的test1.dll两个动态依赖DLL。文件夹结构如下
inf的编写:
由于此处的DLL依赖为示例,不真实存在,故无法测试,只是以此来讲解多层目录资源打包成cab包。
第六、添加MFC窗体。就是一个带界面的ActiveX控件
去掉上边的“确定”和“取消”按钮,然后修改对话框属性:Border改为None,Control改为Ture,ID改为IDD_DIALOG1,Style改为Child,System改为False,Visible改为True,然后在对话框中双击,为对话框添加一个类,如下图:
点击完成,会自动新增了一个类:
在对话框上新增一个按钮,用于测试:
双击该按钮,添加一个点击事件。在CMyDlg.h和CMyDlg.cpp文件中会响应的增加该事件的代码:
将刚创建好的MFC对话框添加到Active中。在activexdemoCtrl.h中引入MyDlg.h并添加一个属性:
然后在activexdemoCtrl类中定义两个消息映射:窗体创建完成消息映射(WM_CREATE)和窗体改变大小消息映射(WM_SIZE)
在VS2015的菜单项“项目”--》“类向导”中,选择要添加到的项目和类中,选择“消息”选项卡,选择WM_CREATE后点击”添加处理程序“按钮和选择WM_SIZE
后点击”添加处理程序“,这样在“现有的处理程序”中就有OnCreate和OnSize这两个函数,点击确定,完成消息映射函数的添加,如图:
点击应用和完成后,在activexdemoCtrl.h和activexdemoCtrl.cpp文件中会自动添加OnCreate()和OnSize()方法。并在activexdemoCtrl.cpp中添加MFC创建的对话框。
重新生成ocx,然后再次反注册和注册,进行测试。结果如下:
第七、ocx更新:
上面注册的ocx在注册表中没有InstalledVersion这个项,需要在inf文件中添加。
inf编辑添加InstalledVersion。如果不添加,可能会出现IE浏览器刷新后一直提示需要重复安装Activex控件。
inf添加了AddReg后的注册表项:
第八、关于ocx控件已经安装成功,但出现“SCRIPT438:对象不支持"xxx"属性或者方法”。以这篇的例子来说,IE浏览器中的Console中会出现错误:“SCRIPT438:对象不支持"initDvr"属性或者方法“的解决办法。
(1)找到IE浏览器上的设置->Internet选项->安全->找到Internet、本地Internet、受信任的站点三个项目下的->自定义级别->找到"对未标记为可安全执行脚本的Activex控件初始化并执行脚本"设置为"启用"。
(2)1的方法太过麻烦,不可以让每台电脑都设置。故通过添加IObjectSafety接口。
在activexdemoCtrl.h中添加:
代码可复制:
//ISafeObject Begin
DECLARE_INTERFACE_MAP()
BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)
STDMETHOD_(HRESULT, GetInterfaceSafetyOptions)(
/*[in]*/ REFIID riid,
/*[out]*/ DWORD __RPC_FAR *pdwSupportedOptions,
/*[out]*/ DWORD __RPC_FAR *pdwEnabledOptions
); STDMETHOD_(HRESULT, SetInterfaceSafetyOptions)(
/*[in]*/ REFIID riid,
/*[in]*/ DWORD dwOptionSetMask,
/*[in]*/ DWORD dwEnabledOptions
);
END_INTERFACE_PART(ObjSafe);
//ISafeObject END
在activexdemoCtrl.cpp中添加:
代码可复制:
/*
* IObjectSafety BEGIN
*/
//Interface map for IObjectSafety
BEGIN_INTERFACE_MAP(CactivexdemoCtrl, COleControl)
INTERFACE_PART(CactivexdemoCtrl, IID_IObjectSafety, ObjSafe)
END_INTERFACE_MAP()
//IObjectSafety member functions
//Delegate AddRef,Release,QueryInterface ULONG FAR EXPORT CactivexdemoCtrl::XObjSafe::AddRef()
{
METHOD_PROLOGUE(CactivexdemoCtrl, ObjSafe)
return pThis->ExternalAddRef();
} ULONG FAR EXPORT CactivexdemoCtrl::XObjSafe::Release()
{
METHOD_PROLOGUE(CactivexdemoCtrl, ObjSafe)
return pThis->ExternalRelease();
} HRESULT FAR EXPORT CactivexdemoCtrl::XObjSafe::QueryInterface(
REFIID iid, void FAR* FAR* ppvObj)
{
METHOD_PROLOGUE(CactivexdemoCtrl, ObjSafe)
return (HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);
} const DWORD dwSupportedBits =
INTERFACESAFE_FOR_UNTRUSTED_CALLER |
INTERFACESAFE_FOR_UNTRUSTED_DATA;
const DWORD dwNotSupportedBits = ~dwSupportedBits; // CStopLiteCtrl::XObjSafe::GetInterfaceSafetyOptions
// Allows container to query what interfaces are safe for what. We're
// optimizing significantly by ignoring which interface the caller is
// asking for.
HRESULT STDMETHODCALLTYPE
CactivexdemoCtrl::XObjSafe::GetInterfaceSafetyOptions(
REFIID riid,
DWORD __RPC_FAR *pdwSupportedOptions,
DWORD __RPC_FAR *pdwEnabledOptions)
{
METHOD_PROLOGUE(CactivexdemoCtrl, ObjSafe) HRESULT retval = ResultFromScode(S_OK); // does interface exist?
IUnknown FAR* punkInterface;
retval = pThis->ExternalQueryInterface(&riid,
(void * *)&punkInterface);
if (retval != E_NOINTERFACE) { // interface exists
punkInterface->Release(); // release it--just checking!
} // we support both kinds of safety and have always both set,
// regardless of interface
*pdwSupportedOptions = *pdwEnabledOptions = dwSupportedBits; return retval; // E_NOINTERFACE if QI failed
} // CStopLiteCtrl::XObjSafe::SetInterfaceSafetyOptions
// Since we're always safe, this is a no-brainer--but we do check to make
// sure the interface requested exists and that the options we're asked to
// set exist and are set on (we don't support unsafe mode).
HRESULT STDMETHODCALLTYPE
CactivexdemoCtrl::XObjSafe::SetInterfaceSafetyOptions(
REFIID riid,
DWORD dwOptionSetMask,
DWORD dwEnabledOptions)
{
METHOD_PROLOGUE(CactivexdemoCtrl, ObjSafe) // does interface exist?
IUnknown FAR* punkInterface;
pThis->ExternalQueryInterface(&riid, (void * *)&punkInterface);
if (punkInterface) { // interface exists
punkInterface->Release(); // release it--just checking!
}
else { // interface doesn't exist
return ResultFromScode(E_NOINTERFACE);
} // can't set bits we don't support
if (dwOptionSetMask & dwNotSupportedBits) {
return ResultFromScode(E_FAIL);
} // can't set bits we do support to zero
dwEnabledOptions &= dwSupportedBits;
// (we already know there are no extra bits in mask )
if ((dwOptionSetMask & dwEnabledOptions) !=
dwOptionSetMask) {
return ResultFromScode(E_FAIL);
} // don't need to change anything since we're always safe
return ResultFromScode(S_OK);
}
/*IObjectSafety END*/
添加完成后重新生成即可。
MFC Activex 开发、ocx打包成cab、部署、测试、自动升级的更多相关文章
- ActiveX控件打包成Cab实现浏览器自动下载安装
前言 我们在浏览器中使用我们自己的一些OCX,或者是DLL这一类的文件,在X86的机器上需要我们手动将这些文件拷贝到Windows/System32 文件夹下面去,然后通过Dos命令regsvr32 ...
- ActiveX控件打包成Cab置于网页中自动下载安装(转载)
原文出自http://www.iteye.com/topic/110834 [背景] 做过ActiveX控件的朋友都知道,要想把自己做的ActiveX控件功能放在自己的网页上使用,那么用户在客户端就必 ...
- ActiveX控件打包成Cab置于网页中自动下载安装 [转]
http://blog.sina.com.cn/s/blog_520c32270100nopj.html 做过ActiveX控件的朋友都知道,要想把自己做的ActiveX控件功能放在自己的网页上使用, ...
- ActiveX控件打包成Cab置于网页中自动下载安装
[背景] http://www.360doc.com/content/13/1120/20/10159093_330853247.shtml 做过ActiveX控件的朋友都知道,要想把自己做的Acti ...
- 将ActiveX打包成CAB发布的注意事项
1.在实现ActiveX组件时,注意VS必须使用管理员身份运行,否则会提示不成功 2.在解决方案中添加一个安装项目 a.在View中点击文件系统,添加对ActiveX项目的输出 b.注册表HKEY_C ...
- C# Activex开发、打包、签名、发布 C# Activex开发、打包、签名、发布 [转]
C# Activex开发.打包.签名.发布 2013-06-22 12:01:20 浏览:3823 一.前言 最近有这样一个需求,需要在网页上面启动客户端的软件,软件之间的通信.调用,单单依靠HTML ...
- C# Activex开发、打包、签名、发布
一.前言 最近有这样一个需求,需要在网页上面启动客户端的软件,软件之间的通信.调用,单单依靠HTML是无法实现了,因此必须借用Activex来实现.由于本人主要擅长C#,自然本文给出了用C# ...
- uniapp打包成H5部署到服务器教程
当前端uniapp写的项目开发完成的时候,需要将页面打包出来,生成H5的静态文件,部署在服务器上,通过服务器链接地址,就可以直接在手机上点开访问 了. 在网上看了一圈,好像没有找到十分详细的教程,这里 ...
- OCX控件打包成CAB并实现数字签名过程
OCX打包CAB并签名过程 一.打包cab 制作cab文件时需要将所有的相关文件都包含进去,可以通过Depends(VC自带的)检查需要的文件.使用inf文件将这些东西都写进去. 1.制作inf文 ...
随机推荐
- [APIO2013]机器人[搜索、斯坦纳树]
题意 题目链接 分析 记 g(d,x,y) 表示从 (x,y) 出发,方向为 d 到达的点,这个可以通过记忆化搜索求出,注意如果转移成环(此时向这个方向走没有意义)要特判. 记 f(l,r,x,y) ...
- zooland 新开源的RPC项目,希望大家在开发的微服务的时候多一种选择,让微服务开发简单,并且容易上手。
zooland 我叫它动物园地,一个构思很长时间的一个项目.起初只是觉得各种通信框架都封装的很好了,但是就是差些兼容,防错,高可用.同时在使用上,不希望有多余的代码,像普通接口一样使用就可以了. 基于 ...
- Javascript如何实现GPU加速?
一.什么是Javascript实现GPU加速? CPU与GPU设计目标不同,导致它们之间内部结构差异很大.CPU需要应对通用场景,内部结构非常复杂.而GPU往往面向数据类型统一,且相互无依赖的计算.所 ...
- web安全入门课程笔记——网站基础与信息搜集
2-1 网站的基本概念 URL统一资源定位符 这是一个动态页面 ?ID 查询条件 后台数据库最有可能:ACCESS Web容器(web容器是一种服务程序,在服务器一个端口就有一个提供相应服务的程序,而 ...
- DVWA渗透测试系列 一 (DVWA环境配置)
DVWA介绍: DVWA是一个渗透测试靶机系统. DVWA具有十个模块:分别是 Brute Force(暴力破解).Command Injection(命令行注入).CSRF(跨站请求伪造).File ...
- openssl证书及配置
我的环境是:Linux+Apache+MySQL+PHP 1.下载openssl 及相关依赖 #yum install -y openssl 2.进入目录 /etc/pki/tls/certs #cd ...
- npm模块之http-proxy-middleware使用教程(译)
单线程node.js代理中间件,用于连接,快速和浏览器同步 Node.js代理简单. 轻松配置代理中间件连接,快速,浏览器同步等. 由流行的Nodejitsu http代理提供. TL;DR 代理/ ...
- PHP学习笔记1
1.什么是PHP? Hypertext Preprocessor(超文本预处理语言). 是脚本语言. 是最流行的网站开发语言. 2.PHP能做什么? 可以生成动态页面内容. 可以创建.打开.读取.写入 ...
- A. Elections
链接 [http://codeforces.com/contest/1043/problem/A] 题意 有n个投票人已经投个对手ai票,让你求最小的k使得k-ai加起来大于,对手得票总和 分析 一个 ...
- 云平台项目--学习经验--jsrender前端渲染模板
jsrender的好处:可以预先自定义一些固定的html标签,在需要显示数据的时候,可以直接传入真实的数据并显示在web页面中,避免了Js编写中的复杂过程:针对高性能和纯字符串渲染并优化,不需要依赖D ...