`
zhaohaolin
  • 浏览: 1003664 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

COM组件开发实践(三)【转】

阅读更多

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

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

Building a Safe ActiveX Control

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

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

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

//  CardScan.cpp : CCardScanApp 和DLL 注册的实现。
#include  " stdafx.h "
#include 
" CardScan.h "
#include 
" comcat.h "
#include 
" strsafe.h "
#include 
" objsafe.h "

CCardScanApp theApp;
const  GUID CDECL BASED_CODE _tlid  =
        { 
0x29959268 0x9729 0x458E , {  0xA8 0x39 0xBB 0x39 0x2E 0xCB 0x7E 0x37  } };
const  WORD _wVerMajor  =   1 ;
const  WORD _wVerMinor  =   0 ;
const  CATID CLSID_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 初始化
BOOL CCardScanApp::InitInstance()
{
    BOOL bInit 
=  COleControlModule::InitInstance();
    
if  (bInit)
    {
    }
    
return  bInit;
}
//  CCardScanApp::ExitInstance - DLL 终止
int  CCardScanApp::ExitInstance()
{
    
return  COleControlModule::ExitInstance();
}
HRESULT CreateComponentCategory(CATID catid, CHAR 
* 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
    size_t len;
    
//  Make sure the provided description is not too long.
    
//  Only copy the first 127 characters if it is.
    
//  The second parameter of StringCchLength is the maximum
    
//  number of characters that may be read into catDescription.
    
//  There must be room for a NULL-terminator. The third parameter
    
//  contains the number of characters excluding the NULL-terminator.
    hr  =  StringCchLength(catDescription, STRSAFE_MAX_CCH,  & len);
    
if  (SUCCEEDED(hr))
    {
        
if  (len > 127 )
        {
            len 
=   127 ;
        }
    }   
    
else
    {
        
//  TODO: Write an error handler;
    }
    
//  The second parameter of StringCchCopy is 128 because you need 
    
//  room for a NULL-terminator.
    hr  =  StringCchCopy(COLE2T(catinfo.szDescription), len  +   1 , catDescription);
    
//  Make sure the description is null terminated.
    catinfo.szDescription[len  +   1 =   ' \0 ' ;
    hr 
=  pcr -> RegisterCategories( 1 & catinfo);
    pcr
-> Release();
    
return  hr;
}
//  HRESULT RegisterCLSIDInCategory -
//       Register your component categories information
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 - Remove entries from the registry
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);
    
//  Mark the control as safe for initializing.
    hr  =  CreateComponentCategory(CATID_SafeForInitializing, 
        _T(
" Controls safely initializable from persistent data! " ));
    
if  (FAILED(hr))
        
return  hr;
    hr 
=  RegisterCLSIDInCategory(CLSID_SafeItem, 
        CATID_SafeForInitializing);
    
if  (FAILED(hr))
        
return  hr;
    
//  Mark the control as safe for scripting.
    hr  =  CreateComponentCategory(CATID_SafeForScripting, 
        _T(
" Controls safely  scriptable! " ));
    
if  (FAILED(hr))
        
return  hr;
    hr 
=  RegisterCLSIDInCategory(CLSID_SafeItem, 
        CATID_SafeForScripting);
    
if  (FAILED(hr))
        
return  hr;
    
return  NOERROR;
}

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

STDAPI DllUnregisterServer(
void )
{
    HRESULT hr;
    AFX_MANAGE_STATE(_afxModuleAddrThis);
    
//  Remove entries from the registry.
    hr = UnRegisterCLSIDInCategory(CLSID_SafeItem, 
        CATID_SafeForInitializing);
    
if  (FAILED(hr))
        
return  hr;
    hr
= UnRegisterCLSIDInCategory(CLSID_SafeItem, 
        CATID_SafeForScripting);
    
if  (FAILED(hr))
        
return  hr;
    
if  ( ! AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))
        
return  ResultFromScode(SELFREG_E_TYPELIB);
    
if  ( ! COleObjectFactoryEx::UpdateRegistryAll(FALSE))
        
return  ResultFromScode(SELFREG_E_CLASS);
    
return  NOERROR;
}

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

hr = UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);

hr
= UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);

这两句代码放在

if  ( ! AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor))

           
return  ResultFromScode(SELFREG_E_TYPELIB);

      
if  ( ! COleObjectFactoryEx::UpdateRegistryAll(FALSE))

           
return  ResultFromScode(SELFREG_E_CLASS);

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

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

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

class  ATL_NO_VTABLE CTestCtrl :
    …
    
public  IObjectSafetyImpl < CTestCtrl, INTERFACESAFE_FOR_UNTRUSTED_CALLER |  INTERFACESAFE_FOR_UNTRUSTED_DATA > ,

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

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 值,你可以对资源文件进行编辑如下

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 代码如下:

< OBJECT  ID ="FuckATL1"   
CODEBASE 
="http://localhost:8080/CardScan.cab"
CLASSID
="CLSID:B548F3C7-2135-4242-920B-A7BDEE6D2BA3"  WIDTH =300  HEIGHT =200
/>

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

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

;  Sample INF file  for  SCRIPTABLEACTIVEX . DLL
[version] 
;  version signature  ( same  for  both NT and Win95 )   do   not  remove
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
;   end  of INF file

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

作者:洞庭散人

出处:http://phinecos.cnblogs.com/     

本博客遵从Creative Commons Attribution 3.0 License ,若用于非商业目的,您可以自由转载,但请保留原作者信息和文章链接URL。

分享到:
评论

相关推荐

    Vue项目组件化工程开发实践方案

    本文将详细介绍Vue项目组件化工程开发实践方案,涵盖组件库、文档工程和例子工程三个方面。通过引入vde-cli脚手架,可以快速生成组件库工程目录结构,并且可以自动更新文档工程和例子工程。 一、组件库工程 组件库...

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

    在现代Web开发中,"Web前端工程化与组件化开发实践"已经成为提升开发效率和代码质量的重要手段。本文将深入探讨这两个概念,并结合具体的实践案例,解析如何在JavaScript开发中应用它们。 首先,前端工程化是指通过...

    com组件学习com组件学习

    C++是COM组件开发的主要语言,使用C++开发COM组件通常会用到 ATL(Active Template Library)或者MFC(Microsoft Foundation Classes)。ATL是一种轻量级的库,专门为COM设计,简化了COM组件的开发过程。MFC则是更...

    C#组件开发简易教程.

    通过学习这个C#组件开发简易教程,你将能够理解组件的基本概念,掌握组件开发的关键技术和实践,为构建高效、可维护的C#应用程序打下坚实基础。在实际开发过程中,不断实践和优化,将使你成为组件开发的专家。

    VC++编写COM组件教程

    **VC++ 编写COM组件教程** COM(Component Object Model)是微软提出的一...以上内容涵盖了创建和使用COM组件的基本知识,通过学习和实践,你可以熟练地利用VC++开发出高效的COM组件,并在不同的应用程序中灵活使用。

    组件化实践代码组件化实践代码

    组件化是一种软件开发方法,它将复杂的应用程序分解为可重用、独立的模块,称为组件。在Android开发中,组件化技术已经成为提高代码复用性、可维护性和团队协作效率的重要手段。本实践代码主要关注如何在实际项目中...

    前端组件化开发实践 -1

    【前端组件化开发实践 -1】 前端开发领域中,组件化是一种重要的开发模式,它能够有效地管理和控制项目复杂性。随着技术的发展,组件化已成为现代前端框架的核心特性,如React和Vue等。美团点评技术团队在实践中也...

    delphi 组件开发 入门必看

    对于想要入门Delphi组件开发的初学者来说,了解并掌握相关知识至关重要。组件是Delphi编程的核心元素,它们是可重用的代码模块,封装了特定的功能,可以在界面上直接拖放,极大地提高了开发效率。 首先,我们需要...

    asp组件开发指南

    ASP组件开发指南主要涵盖了几大核心知识点,这些知识点对于深入理解和构建高效、可复用的ASP应用程序至关重要。本文将详细阐述这些关键概念。...不断探索和实践,将有助于你在ASP组件开发领域积累深厚的专业技能。

    MapGis组件开发手册

    《MapGis组件开发手册》是一本专注于MapGis组件技术的权威指南,它深入浅出地阐述了组件开发的基本理论和实践技巧。MapGis作为一款强大的地理信息系统(GIS)软件,其组件化开发模式为用户提供了丰富的自定义功能和...

    Delphi组件开发指南中文版

    《Delphi组件开发指南中文版》是一本专为Delphi开发者设计的详尽教程,旨在帮助读者深入理解和掌握在Delphi环境下进行组件开发的核心技术。Delphi是一款强大的面向对象的集成开发环境(IDE),以其高效的编译器和...

    基于组件开发的组件选择过程

    基于组件开发(Component-Based Development,简称CBD)是一种现代软件工程方法论,其核心思想在于通过重用预先构建的软件组件来构建新的软件系统,以此提高软件开发效率,降低开发成本,提升软件质量。然而,CBD的...

    VC-COM.zip_ATL vs2010_ATL开发com组件_com开发 vs_vs com组件开发

    开发com组件_com开发 vs_vs com组件开发** 在软件开发中,组件(Component)是一种可重用的代码单元,它可以独立于应用程序而存在,并能被多个应用程序共享。COM(Component Object Model)是微软提出的一种组件...

    COM组件对象模型实践源码

    在实践中,你将学习到如何使用 ATL(Active Template Library)或MFC(Microsoft Foundation Classes)来简化COM组件的开发。ATL是微软提供的一组C++模板库,专门用于创建高效、轻量级的COM组件,而MFC则提供了更...

    iOS App组件化开发实践1

    在iOS应用开发中,组件化是一种重要的架构设计方法,它能有效地提高代码的复用性、可维护性和团队协作效率。本文将探讨iOS App组件化的实践,主要关注以下几个方面: 1. **组件化概念**:组件化是将一个大型的应用...

    visual C#基于组件的开发

    《Visual C#基于组件的开发》是一份深入探讨C#组件开发技术的宝贵资源,它涵盖了从基础到高级的各种主题,旨在帮助开发者更好地理解和实践组件编程。这份资料被分为三个部分,每个部分由一系列PDG文件组成,这些文件...

    iOS App 组件化开发实践

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

    COM组件 教程&源代码

    这个“COM组件教程&源代码”资源显然是为初学者设计的,旨在通过详细的文字说明和图像指导,帮助学习者理解并实践COM组件的开发。 COM组件的核心概念包括: 1. **组件**: COM组件是实现了COM接口的二进制模块,...

    com组件_vs2013

    总的来说,这个资源包是学习和实践COM组件、ATL和MFC的好材料,涵盖了从基础组件开发到高级应用的多个层面。通过这些项目,开发者可以深入理解COM的原理,掌握ATL和MFC的使用技巧,提升在Windows平台上构建组件和...

Global site tag (gtag.js) - Google Analytics