`
dato0123
  • 浏览: 917786 次
文章分类
社区版块
存档分类
最新评论

COM组件开发实践(三)

 
阅读更多
前面篇文章分MFC ActiveX用程序和使用ATL开发ActiveX简单实例,但两个问题需要解

1标记ActiveX控件安全的控件 2)控件名。本文将结这两简单的介

Building a Safe ActiveX Control

如何不想办法将控件标记为安全的,就会在Web页面与控件进行交互时出现如下图的警告信息:

下面将分别介绍在MFC ActiveXATL中如何标记一个控件为安全的控件。

要标记一个MFC ActiveX控件为安全,可以仿照下面代码修改而得:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->//CardScan.cpp:CCardScanApp和DLL注册的实现。
#include"stdafx.h"
#include
"CardScan.h"
#include
"comcat.h"
#include
"strsafe.h"
#include
"objsafe.h"

CCardScanApptheApp;
constGUIDCDECLBASED_CODE_tlid=
{
0x29959268,0x9729,0x458E,{0xA8,0x39,0xBB,0x39,0x2E,0xCB,0x7E,0x37}};
constWORD_wVerMajor=1;
constWORD_wVerMinor=0;
constCATIDCLSID_SafeItem=
{
0xB548F3C7,0x2135,0x4242,{0x92,0x0B,0xA7,0xBD,0xEE,0x6D,0x2B,0xA3}};

//{0x36299202,0x9ef,0x4abf,{0xad,0xb9,0x47,0xc5,0x99,0xdb,0xe7,0x78}};
//CCardScanApp::InitInstance-DLL初始化
BOOLCCardScanApp::InitInstance()
{
BOOLbInit
=COleControlModule::InitInstance();
if(bInit)
{
}
returnbInit;
}
//CCardScanApp::ExitInstance-DLL终止
intCCardScanApp::ExitInstance()
{
returnCOleControlModule::ExitInstance();
}
HRESULTCreateComponentCategory(CATIDcatid,CHAR
*catDescription)
{
ICatRegister
*pcr=NULL;
HRESULThr
=S_OK;
hr
=CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(
void**)&pcr);
if(FAILED(hr))
returnhr;
//MakesuretheHKCR/ComponentCategories/{..catid}
//keyisregistered.
CATEGORYINFOcatinfo;
catinfo.catid
=catid;
catinfo.lcid
=0x0409;//english
size_tlen;
//Makesuretheprovideddescriptionisnottoolong.
//Onlycopythefirst127charactersifitis.
//ThesecondparameterofStringCchLengthisthemaximum
//numberofcharactersthatmaybereadintocatDescription.
//TheremustberoomforaNULL-terminator.Thethirdparameter
//containsthenumberofcharactersexcludingtheNULL-terminator.
hr=StringCchLength(catDescription,STRSAFE_MAX_CCH,&len);
if(SUCCEEDED(hr))
{
if(len>127)
{
len
=127;
}
}
else
{
//TODO:Writeanerrorhandler;
}
//ThesecondparameterofStringCchCopyis128becauseyouneed
//roomforaNULL-terminator.
hr=StringCchCopy(COLE2T(catinfo.szDescription),len+1,catDescription);
//Makesurethedescriptionisnullterminated.
catinfo.szDescription[len+1]='/0';
hr
=pcr->RegisterCategories(1,&catinfo);
pcr
->Release();
returnhr;
}
//HRESULTRegisterCLSIDInCategory-
//Registeryourcomponentcategoriesinformation
HRESULTRegisterCLSIDInCategory(REFCLSIDclsid,CATIDcatid)
{
//Registeryourcomponentcategoriesinformation.
ICatRegister*pcr=NULL;
HRESULThr
=S_OK;
hr
=CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(
void**)&pcr);
if(SUCCEEDED(hr))
{
//Registerthiscategoryasbeing"implemented"bytheclass.
CATIDrgcatid[1];
rgcatid[
0]=catid;
hr
=pcr->RegisterClassImplCategories(clsid,1,rgcatid);
}
if(pcr!=NULL)
pcr
->Release();
returnhr;
}

//HRESULTUnRegisterCLSIDInCategory-Removeentriesfromtheregistry
HRESULTUnRegisterCLSIDInCategory(REFCLSIDclsid,CATIDcatid)
{
ICatRegister
*pcr=NULL;
HRESULThr
=S_OK;
hr
=CoCreateInstance(CLSID_StdComponentCategoriesMgr,
NULL,CLSCTX_INPROC_SERVER,IID_ICatRegister,(
void**)&pcr);
if(SUCCEEDED(hr))
{
//Unregisterthiscategoryasbeing"implemented"bytheclass.
CATIDrgcatid[1];
rgcatid[
0]=catid;
hr
=pcr->UnRegisterClassImplCategories(clsid,1,rgcatid);
}
if(pcr!=NULL)
pcr
->Release();
returnhr;
}
//DllRegisterServer-将项添加到系统注册表

STDAPIDllRegisterServer(
void)
{
HRESULThr;
AFX_MANAGE_STATE(_afxModuleAddrThis);
if(!AfxOleRegisterTypeLib(AfxGetInstanceHandle(),_tlid))
returnResultFromScode(SELFREG_E_TYPELIB);
if(!COleObjectFactoryEx::UpdateRegistryAll(TRUE))
returnResultFromScode(SELFREG_E_CLASS);
//Markthecontrolassafeforinitializing.
hr=CreateComponentCategory(CATID_SafeForInitializing,
_T(
"Controlssafelyinitializablefrompersistentdata!"));
if(FAILED(hr))
returnhr;
hr
=RegisterCLSIDInCategory(CLSID_SafeItem,
CATID_SafeForInitializing);
if(FAILED(hr))
returnhr;
//Markthecontrolassafeforscripting.
hr=CreateComponentCategory(CATID_SafeForScripting,
_T(
"Controlssafelyscriptable!"));
if(FAILED(hr))
returnhr;
hr
=RegisterCLSIDInCategory(CLSID_SafeItem,
CATID_SafeForScripting);
if(FAILED(hr))
returnhr;
returnNOERROR;
}

//DllUnregisterServer-将项从系统注册表中移除

STDAPIDllUnregisterServer(
void)
{
HRESULThr;
AFX_MANAGE_STATE(_afxModuleAddrThis);
//Removeentriesfromtheregistry.
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem,
CATID_SafeForInitializing);
if(FAILED(hr))
returnhr;
hr
=UnRegisterCLSIDInCategory(CLSID_SafeItem,
CATID_SafeForScripting);
if(FAILED(hr))
returnhr;
if(!AfxOleUnregisterTypeLib(_tlid,_wVerMajor,_wVerMinor))
returnResultFromScode(SELFREG_E_TYPELIB);
if(!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
returnResultFromScode(SELFREG_E_CLASS);
returnNOERROR;
}

这里值得注意的一个地方是DllUnregisterServer函数,在这段代码中,我是将

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->hr=UnRegisterCLSIDInCategory(CLSID_SafeItem,CATID_SafeForInitializing);

hr
=UnRegisterCLSIDInCategory(CLSID_SafeItem,CATID_SafeForScripting);

这两句代码放在

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->if(!AfxOleUnregisterTypeLib(_tlid,_wVerMajor,_wVerMinor))

returnResultFromScode(SELFREG_E_TYPELIB);

if(!COleObjectFactoryEx::UpdateRegistryAll(FALSE))

returnResultFromScode(SELFREG_E_CLASS);

这两句代码的前面,如果你查阅MSDN,将会发现它上面的顺序和我是相反的,这应该是微软的一个错误代码,如果按照MSDN的代码来写,则你使用regsvr32 -uCardScan.ocx反注册时会报下面的错误:

调整为我所说的顺序就没问题了。

2)要标记使用ATL写的ActiveX控件为安全的控件,这比MFC要简单的多,只需要在控件头文件中增加几行代码就可以了:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->classATL_NO_VTABLECTestCtrl:

publicIObjectSafetyImpl<CTestCtrl,INTERFACESAFE_FOR_UNTRUSTED_CALLER|INTERFACESAFE_FOR_UNTRUSTED_DATA>,

然后在COM映射表中增加一项:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->BEGIN_COM_MAP(CTestCtrl)

COM_INTERFACE_ENTRY(IObjectSafety)
END_COM_MAP()

Building a Signed ActiveX Control

ActiveX控件是个危险的东西,如果不对其合法性进行数字签名和验证,IE是会拒绝其安装的。

工具包准备:CABARC.exe, cert2spc.exe, makecab.exe, makecert.exe, signcode.exe(或新版本中的signtool),以上小工具都可以在VS的安装路径下"Common7"Tools"Bin找到,或去微软官方网站上下载。

ActiveX控件的安装过程中,一部分工作就是自注册,这需要控件在VERSIONINFO结构中定义OLESelfRegister值,你可以对资源文件进行编辑如下

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->BEGIN
BLOCK
"StringFileInfo"
BEGIN
BLOCK
"080403a8"
BEGIN
VALUE
"CompanyName","TODO:<公司名>"
VALUE
"FileDescription","TODO:<文件说明>"
VALUE
"FileVersion","1.0.0.1"
VALUE
"InternalName","CardScan.ocx"
VALUE
"LegalCopyright","TODO:(C)<公司名>。保留所有权利。"
VALUE
"OLESelfRegister","/0"
VALUE
"OriginalFilename","CardScan.ocx"
VALUE
"ProductName","TODO:<产品名>"
VALUE
"ProductVersion","1.0.0.1"
END
END
BLOCK
"VarFileInfo"
BEGIN
VALUE
"Translation",0x804,936
END
END

打包为CAB文件

因为ActiveX控件要放在网站上供客户下载到本地,因此压缩是必需的。一段典型的html代码如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><OBJECTID="FuckATL1"
CODEBASE
="http://localhost:8080/CardScan.cab"
CLASSID
="CLSID:B548F3C7-2135-4242-920B-A7BDEE6D2BA3"WIDTH=300HEIGHT=200
/>

CODEBASE就指明了要下载的压缩包,其中包含了oxcdll控件等所需要的文件。

通常CAB文件包含了一个INF文件,它用来描述CAB文件的所有细节信息,下面举个简单例子,代码如下:

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->;SampleINFfileforSCRIPTABLEACTIVEX.DLL
[version]
;versionsignature(sameforbothNTandWin95)donotremove
signature
="$CHICAGO$"
AdvancedINF
=2.0

[Add
.Code]
CardScan
.ocx=CardScan.ocx
CardScan
.inf=CardScan.inf

[CardScan
.ocx]
file-win32-x86
=thiscab
clsid
={B548F3C7-2135-4242-920B-A7BDEE6D2BA3}
FileVersion
=1,0,0,1
RegisterServer
=yes

[CardScan
.inf]
file
=thiscab
;endofINFfile

至于打包就不赘述了,详尽的图解过程请看《如何给ActiveX数字签名(Step by Step, Delphi)

分享到:
评论

相关推荐

    Web前端工程化与组件化开发实践

    Web前端工程化与组件化开发实践

    iOS App组件化开发实践1

    iOS App组件化开发实践1

    Kotlin+组件化开发实践—开源项目Designer-App

    Kotlin+组件化开发实践—开源项目Designer-App网上大神的项目,学习一下

    iOS App 组件化开发实践

    而现在组件化之后,某个业务组件只需要 10s~20s 左右。在依赖 二进制化组件的情况下,业务组件编译速度一般低于 10s。 • 分工更为明确,从而提升开发效率。 • 灵活,耦合低。 • 结合 MVVM。非常细致的单元测试,...

    软件工程中的代码重用与组件化开发实践.pptx

    软件工程中的代码重用与组件化开发实践.pptx

    C++中COM组件思想实践

    在开发一个产品时,其往往有很多子模块,子业务和子功能,这些都可以抽象成组件(C++中本质表现就是一个类)。...本文以某产品(产品业务为Business)的子功能AAAAAA为例,探讨一下COM组件思想在开发中的应用。

    c# 组件 开发.rar c# 组件 开发.rar

    c# 组件 开发.rar c# 组件 开发.rar c# 组件 开发.rar

    组件化开发全新思路!实践微信小程序高阶段开发+项目案例实战课程 附素材和源码

    组件化开发全新思路!实践微信小程序高阶段开发+项目案例实战课程 附素材和源码

    vxworks程序开发实践

    本书介绍了嵌入式实时多任务操作系统VxWorks及其主机环境Tornado,并实践性地描述了其上的程序开发过程。书中详细介绍了VxWoks各个重要的组件,包括多任务环境、内存管理、IO系统(包括字符设备)、文件系统和网络...

    小程序组件化开发ppt

    0623-changong-小程序组件化开发实践 分析透彻,设计先进.可以用作培训

    前端组件化开发实践 -1

    前言一位计算机前辈曾说过:Controlling complexity is the essence of computer programming.随着前端开

    AWTK开发手册-AWTK开发实践指南-中文手册.pdf

    AWTK开发手册-AWTK开发实践指南-中文手册.pdf AWTK = Toolkit AnyWhere 随着手机、智能手表等便携式设备的普及,用户对 GUI 的要求越来越高,嵌入式系统对高性能、高可靠性、低功耗、美观炫酷的 GUI 的需求也...

    报表控件Cell组件、插件

    软件简介:Cell组件、插件是用友华表公司在长期开发实践的基础上推出的功能强大、技术成熟的报表 二次开发工具;是第一个国产ActiveX商业组件; Cell组件适用于Windows环境下各种开发工具(如VB, VC,Visual ...

    VUE.JS组件化开发实践

    公司目前制作一个H5活动,特别是有一定统一结构的活动...这里首先简单说下web前端组件化开发方式的历程:最早的组件化结构,代码结构可能如下:将同功能的组件文件放到同一目录下,结构清晰、职责明确,视图、样式、脚

    华表cell组件帮助手册

    Cell5.1产品分Cell组件5.1和Cell插件5.1两个姐妹产品,它们是北京用友华表软件技术有限公司在长期开发实践的基础上推出的功能强大、技术成熟的报表二次开发工具。 Cell组件(Activex 控件,扩展名为OCX)主要适用于...

    jQuery应用开发实践指南

    资源名称:jQuery应用开发实践指南内容简介:这是一本完全以实例方式来全方位讲解jQuery应用开发的著作,由Ajax领域的技术权威撰写。书中不仅详细讲解了jQuery的各种组件的功能特性和jQuery应用开发的流程与方法,...

    用ActionScript开发高级可视化组件

    5. 组件设计的最佳实践 6. 例子:创建一个复合组件 7. 疑难问题 简单组件一般都是现存Flex 组件的子类,它们通过设置skpins 或styles 属性来修改父组 件的外观,或者添加一些新的功能。比如,为Button 控件增加一个...

    基于Android开发的组件化应用与实践.pdf

    基于Android开发的组件化应用与实践.pdf

    移动端iOS组件化详解.docx

    组件化开发则能够解决这一问题,而且经过业界近年来的探索与实践,慢慢地这已经成为了移动端开发架构的主流方式,并且市面上也已经开源了不少组件化实施方案。但现成的并不一定就是最好的,只有经过实践才能知道什么...

Global site tag (gtag.js) - Google Analytics