admin 管理员组

文章数量: 1086019


2024年3月21日发(作者:instruments近义词)

维普资讯

-一 。一… 

实用第一 智慧密集 

………….… …… ……… …. … … . … 。 

ActiveX网页 控件 

张德强 

摘要 

ActiveX插件技术广泛地运用于B/S系统中,本文通过一个项目实例,详细介绍用 

ATL开发和部署ActiveX网页控件的过程。学习使用ActiveX让浏览器访问客户端 

的硬件资源。 

关键词 

ATL,ActiveX控件,COM组件 

刖吾 

COM是Microsoft组件对象模型的简称,是一个说明如何 

建立可动态交替更新组件的规范。它提供了客户和组件为保证 

能够相互操作应该遵循的标准。该标准对于组件架构的重要性 

同其他任何一个具有可交替更新部分的系统是一样的。 

COM标准包括规范和实现两大部分,规范部分定义了组 

件和组件之间通信的机制,这些规范不依赖于任何特定的语言 

在B/S结构的系统中,出于安全性考虑一般不准许浏览 

器访问客户端的硬件资源,如控制打印机、照相机等。对于一 

个完善系统来说,往往很多时候又需要控制这些资源。通过在 

浏览器中插入ActiveX插件是一种很好的解决方式。 

在实际的项目开发中,遇到系统登录需要增加物理身份识 

和操作系统,只要按照该规范,任何语言都可以使用;COM 

标准的实现部分是COM库,COM库为COM规范的具体实现 

提供了一些核心服务。 

别。即在系统登录的时候,除了要验证用户名和密码外,还需 

要验证硬件USB KEY上的信息。具体业务流程为:客户端程 

序读取用户硬件USB KEY里的个人信息(即加密认证信 

息),提交给认证服务器进行认证,认证服务器通过身份识别 

后,业务系统通过解析返回的XML信息判断用户是否合法有 

效,建立起用户和业务系统的信任通道。通过本例的ActiveX 

在COM模型中,对象本身对于客户来说是不可见的,客 

户请求服务时,只能通过接口进行。 一般接口是不会改变的。 

3.ATL 

ATL(Active Template Library)是微软的活动模板库,是 

控件来完成读取硬件USB KEY的信息。硬件USB KEY选用飞 

天诚信的ePassl000ND产品。 

个产生C++/COM代码的框架,专门用于开发COM组 

件。ATL提供了小巧、高效、灵活的类,这些类为创建可相互 

操作的COM组件提供了基本的设施。ATL完全面向COM组 

件,其结构完全针对COM中的诸多规范。是编写COM组件的 

二、概念 

1.ActiveX 

快捷工具。 

ActiveX是Microsoft提出的一组使用COM(Component Ob— 

ject Model,组件对象模型)使得软件组件在网络环境中进行交 

互的技术集。它与具体的编程语言无关。作为针对Internet应 

用开发的技术,ActiveX被广泛应用于Web服务器以及客户端 

的各个方面。 

ActiveX是从Microsoft的复合文档技术一OLE成长起来 

的。其基本的出发点是想让某个软件通过一个通用的机构为另 

三、实现 

1.项目 

打开Visual Studio.Net 2005,建立_一个解决方案或项目 

DeanUSBKey。在项目类型中选择Visual C++下的ATL选项, 

在模板中选择“ATL Project”,项目名为DeanUSBKey。点击 

确定,系统就在指定的目录下建 了DeanUSBKey项目和解决 

方案。 

个软件提供服务,可以将其插入到Web网页或其他应用程 

序中,在Intemet上使用。ActiveX特点是:一般软件需要用户 

点击确定后,会出现建立ATI 项目向导对话框,引导用 

户快捷方便地建立ATI 项目。点击下一步,进入项目属性设 

置对话框,如图1所示。可以通过该对话框选择属性化和发布 

方式等。 

单独下载然后执行安装,而ActiveX插件是当用户浏览到特定 

的网页时,IE浏览器即可自动下载并提示用户安装。但安装 

的一个前提是必须经过用户的同意及确认。 

2 C0M 

24

2007,10

..

1___

,毫-——

巧与一

|.1,|'一__ 

维普资讯

PROGRA啊LAHGU柏E………………………… …………, …………………… ………………….….…. 

图1项目属性设置对话框 

说明如下: 

Attributed即属性化,支持属性化编程,是未来的发展方 

向,是IDL方案的一种替代方案。 

Dynamic—link library(DLL)即动态链接库,表示建立一个 

DLL的组件程序。 

Executable(EXE)即可执行文件,表示建立一个EXE的组 

件程序。 

Service(EXE)即服务,表示建立一个系统服务组件程序, 

系统启动后就会加载并执行的程序。 

Allow merging of proxy/stub code即允许合并代理/存根代 

码,选择该项表示把“代 存根”代码合并到组件程序中, 

否则需要单独编译,单独注册代理存根程序。 

Support MFC即支持MFC,建议不要选择,除非有特殊的 

原因,比如原来的程序是基于MFC的,组件必须要MFC的支 

持。一般在写ATL程序,不选择该项。但是很多VC程序员对 

于MFC的数据集合类和字符串类依赖很大,建议采用STL中 

的相关类进行替代。具体替换方案:std::stirng代替MFC中 

的CString;std::vector代替MFC的数组类如CArray,CPtrAr- 

ray等;std::list替换MFC中的CList等列表类;对于BSTR建 

议采用CComBSTR类,或_bstrJ类,本例子中就会用到该类; 

Support COM+1.0支持事务处理的COM+功能。 

选择如图l所示的选项,点击完成。ATL Prejeet项目就生 

成好了,系统会在指定目录下生成一系列文件,ReadMe.txt里 

有各文件的文件说明。尤其要注意接口定义语言文件 

(DeanUSBKey.id1),它描述了对象的接口细节。 

2.组件 

在COM模型中,客户请求服务时,是通过接口和组件进 

行交互的。现在还是一个空的ATL项目,还没有任何组件。 

添加组件,也就是添加ATL对象类。在DeanUSBKey项目 

上点击右键,添加类,弹出对话框。在类别中选择ATL。在模 

板中选择“ATL Simple Object”即ATL简单对象。点击确定, 

出现建立组件向导,如图2所示。在Short Name输入组件名称 

USBKey,其他内容系统会自动填写。注意组件名称不能和项 

目名称重名。点击下一步进入组件选项设置界面,如图3所 

示。 

图2 ATL简单对象组件名字对话框 

图3 ATL简单对象组件选项对话框 

具体选项说明如下: 

Threading model即线程模型,COM中的线程,这是一个复 

杂的部分。选“单元”(Apartment),它代表当在线程中调用组 

件函数的时候,这些调用会排队进行。可以参看{COM技术 

内幕》一书。 

Interface即接口,双重(Dua1),双重接口表示在一个接口 

中,同时支持自定义接口和IDispatch接口。这个非常重要, 

为了使组件能够在脚本中使用,必须选择双重接口选项。因为 

脚本语言的解释器只认识IDispatch接口。自定义接口 

(Custom),直接实现的是IUnknown接口。 

Aggregation即聚合,写的组件,将来是否允许被其他人以 

聚合方式(有聚合和包容两种方式)使用。Only(只能创建为聚 

合),有点类似C++或Java中的不能直接创建实例的虚类, 

如果不是处于设计目的,一般这个选项不用。大多数情况下支 

维普资讯

…………… ……………………………………… …~ 

实用第一 智慧密集 

持“聚合”,所以我们选择“Yes”。 

//得到序列号 

unsigned long snl2】=(0): 

retval=epas

GetProperty(epsHandle. 

_

ISupportErrorlnfo是否支持丰富信息的错误处理接口。 

Connection points即连接点,是否支持连接点接口(事 

件、回调)。 

IObjectWithSite是否支持IE的调用。 

EPAS_PROP_SERNUM,NULL.sn,sizeof(sn)): 

if(F UCCESS!=retva1) 

(return ReturnError(retva1):) 

选择如图3所示的选项,点击完成。USBKey的组件建立 

charmjn l8}1024+17】=(0): 

完成。在生成的USBKey.cpp里将是接口IUSBKey的实现。 

3.接口 

在类视图中,IUSBKey接口上点击鼠标右键。在添加项里 

有添加方法和属性,选择添加方法。打开图4所示的添加接口 

方法对话框。添加接口方法GetContent,并添加接口方法的参 

数。【in】表示参数方向是输入;【out】表示参数方向是输出; 

【out,retval】表示参数方向是输出,同时可以作为函数运算结果 

的返回值。一个函数中,可以有多个【in】、【out】,但【retval】只 

能有一个,并且要和【out】组合后在最后一个位置。详细的定 

义说明可以参考IDL的语法说明。 

图4添加接口方法对话框 

在USBKey.cpp文件里添加函数GetContent的具体实现过 

程。核心代码如下: 

STDMETHODI MP CUSBKey:: GetContent(LONG IFlags, 

BSTR pUSBContent 1 

( 

EPAS_STATUS retval;//状态 

EPAS

_

HANDLE epsHandle;//EPAS句柄 

//创建设备句柄 

retval=epas

_

CreateContext(&epsHandle,0,EPAS—API— 

VERSION)://调用EPAS的API函数访问USB Key硬件 

If(FT _SUCCESS != retval )

{return ReturnError(retva1);)//返回相应的错误 

,,扎开设备 

retval=epas

_

OpenDevice(epsHandle,IFlags,(void★) 

szApplD): 

.f(FT SUCCESS!=retva1) 

{return ReturnError(retva1);) 

与 

sprintf

_

s(m_sn, %08X%08X ,snl 1】.snl01): 

//以16进制打印到字符串m n中得到加密字符串 

//1、登录 

char Sl80】= 1 234 ://登录密码 

retval=epas

_

Verify(epsHandle,EPAS_VERIFY USER_PIN, 

(unsigned char★)S,4): 

if(FT_sUCCESS!=retva1)(return ReturnError(retva1):) 

//2、打开文件 

EPAS

__

FILEINF0 epsFilelnfo=(0): 

unsigned long epsFilelD=Oxl 234;//文件编号 

retval=epas

_

OpenFile(epsHandle,0,epsFilelD,&eps— 

Filelnfo,sizeof(epsFilelnfo)): 

if(FT__SUCCESS!=retva1)(return ReturnError(retva1): ) 

//3、读取文件内容 

unsigned long rLen=0: 

unsigned char rBu仟【8★1 024】=(0): 

ZeroMemory(rBu仟.8★1 024): 

retval=epas

_

Read(epsHandle.0,0.rBuff,epsFileln- 

fo.ulFileSize.&rLen): 

if(F UCCESS l=retva1)(return ReturnError(retva1):) 

//4、关闭文件 

retval=epas

_

CIoseFile(epsHandle): 

//关闭设备,删除Context 

retval=epas

_

CIoseDevice(epsHandle): 

retval=epas

_

DeleteContext(epsHandle): 

strcat s(m_sn,(char★)rBuff): 

pUSBContent=com

_

util:: ConvertSt ngToBSTR((char 

)r_sn): 

return S

_

OK: 

) 

为了能在函数中使用USBKey厂家提供的访问函数和使用 

BSTR类.需在stdafx.h头文件里面引入相应的.h和.1 文 

件。具体如下: 

#include FT_ND PI.h //ePasslO00ND的接口头文件 

#include comutil.h 

#Dragma comment(1ib, FT D PI.1ib ) 

物ragma comment(1ib, comsuppw.1ib ) 

如果编译通过,VS.Net IDE会打开窗口选择执行控件的外 

部文件。选择regsvr32,编译成功后,组件会自动注册。可以 

在系统组件服务里面查看刚注册的组件DeanUSBKey。 

4.错误处理 

COM方法通过返回HRESULT来报告错误,其他信息异常 

可以通过IErrorlnfo接口提供给客户端,这里主要讲述HRE- 

SULT返回COM方法错误。 

维普资讯

……t

PROG删圳G弧雠……………………………………….,…………………….…………………………… 

HRESULT由一个32位代码组成。分为四部分,如下: 

Field Sevedty l Rese l Facility l code 

Bit(8) 31 l 29—30 l l6—28 l o一15 

各字段说明: 

Severity字段是其中最重要的一个。当一个方法返回时若 

该字段被设置了值,就说明发生了一个错误。该字段使所有的 

COM错误代码显示为负的十进制整数。 

Reserved字段目前是预留字段。 

Facility字段为错误类别代码,总共表示8192种错误,由 

个集中的机构负责分配这些种类。 

Code字段提供了一个可容纳65536个代码的空间。具体 

的错误代码就在该字段里面体现。 

在读取USBKey信息时,捕获的错误做处理,以COM错 

误的形式抛出。即把前16位改为0xa0FF,代码如下: 

LONG CUSBKey::ReturnError(LONG retva1) 

f return 0xa0FF0000+retval;) 

5.实现IObjectSafety接口 

ActiveX控件的编写到此就可以结束了,但在浏览器使用 

该控件的过程中,经常都会弹出现在运行的脚本不安全的提 

示。如果给客户使用,将会带来极大不便。可以通过实现lOb— 

jectSafety接口来解决。ATL在类IObjectSafetylmpl中提供了此 

接口的实现。如果浏览器发现控件支持IObjectSafety,就在导 

入控件之前调用IObjectSafety::SetlnterfaceSafetyOptions方法来 

确保安全性脚本操作,就不会弹出提示对话框。 

在USBKey。h文件里继承类列表的末尾(class 

ATL

NO

VTABLE CUSBKey)加入如下语句: 

public IObjectSafetylmpl<CUSBKey,INTERFACESAFE_FOR— 

UNTRUSTED

_

CALLER l INTERFACESAFE__FOR_UNTRUSTED_ 

DA1.A> 

并在COM映射里添加以下行(黑体部分): 

BEGIN

_

COM MAP(CUSBKey) 

COM INTERFACE ENTRY(IObjectSafety) 

END

_

COM

_

MAP() 

四、测试 

在网页里通过脚本语言调用ActiveX控件DeanUSBKey。可 

以通过VBScript和JAVAScript来调用。为了能在脚本语言里使 

用控件接口,需知道接口的classid,可以查看接口的注册表脚 

本文件USBKey。rgs找到classid值。调用代码如下: 

<object classid= clsid:4F3320E4—4B66—4C85—8538— 

6E1 7699AAB46 id= Dean name= Dean ></object> 

<fOrm id= f0rm1 name= fOrm1 method= post ac— 

tion=~> 

<a href= 撑 onclick= return CalIUSB(): >jS调用Ac- 

tiveX测试</a> 

<input id: Write name= Write type= button val— 

ue= vb调用ActiveX测试 /> 

</form> 

<SCRIPT LANGUAGE= JavaScript > 

<!一 

//JavaScript调用Demo 

function CalIUSB() 

f 

try f 

var USBContent=Dean.GetContent(O): 

alert(USBContent): 

)catch(e)f 

alert( 错误号: +e.number) 

) 

return false; 

) 

一一

> 

</SCRIPT> 

<script language= VBScript type= text/vbscript > 

VBScript调用Demo 

Sub Write OnClick 

On Error Resume Next 

USBContent=Dean.GetContent(O) 

Msg Box USBContent 

MsgBox(err.number and&hff) 

End Sub 

</script> 

五、部署 

Internet软件分发单位是“软件包”,它由包含。INF文件 

或软件分发。OSD文件(或两者都包括)的。CAB文件所组 

成。一个分发单位也可以包含软件组件,如ActiveX控件, 

DLL文件等。 

1。INF文件编写 

INF文件是一个文本文件,指定运行控件所需要下载或者 

呈交的文件(比如.DLL或者其他.OCX)。一个。INF文件就捆 

绑了.CAB压缩文件所有的必须文件。缺省情况下,与现有硬 

盘中文件版本号相同的文件不被下载。INF文件的代码如F: 

【version】 

signature= ¥CHICAGO¥ 

AdvancedlNF=2.0 

【Add.Code】 

FT D PI.dll=FT D PI。dU 

DeanUSBKey.dll=DeanUSBKey。dll 

【FT D PI.dII】 

file—win32一x86=thiscab 

DestDir=11 

FileVersion=1.0,6,413 

【DeanUSBKey.dll】 

file—win32一x86=thiscab 

(下转第39页) 

维普资讯

---

n朋 ………..………………… -………… .…………………………………… .…… ……………… 

是比较复杂的问题.要开发使用功能强大、性能稳定的数据 

库,需要掌握的知识很多。特别是对EDB数据库进行操作时 

由于函数参数较多往往嵌套多个结构体,而且比较复杂,涉及 

到很多的结构体和指针变量,在写代码时要特别注意指针和内 

存的问题,指针要及时进行请空。另外EDB有一些特有的API 

函数,要注意使用,调试错误一般都是集中在这两方面。 

if(!CeFlushDBVol(&calljiluGuid)) 

f 

AfxMessageBox(J( 缓冲介质失败 ¨: 

return: 

) 

//3、卸载数据库卷 

|f(!CeUnmountDBVol(&calljiluGuid)) 

f 

AfxMessageBox(J( uninstall val failed )): 

CDialog::OnCIose(): 

} 

CloseHandle(hSession): 

CDialog::OnCIose(): 

) 

参考文献: 

【1】汪兵,李存斌等.EVC高级编程及其应用开发【M】.中国水 

利水电出版社,2005年1月. 

【2】傅曦,齐字等.Windows Mobile手机应用开发【M】.人民邮 

电出版社,2005年6月. 

三、结语 

通过上面的实例介绍,可以初步掌握EDB数据库的常用 

操作技术,能够根据需要对数据库进行开发应用。数据库开发 

【3】田东风,Windows CE应用程序设计【M】.机械工业出版社 

2005年9月. 

(收稿日期:2007年8月19日) 

(上接第27页) 

RegisterServer=yes 

(5)选择“Don’ save”,一直点击下一步,直到完成。 

3.自动安装, 

clsid={4F3320E4—4B66—4C85—8538—6E1 7699AAB46} 

DestDir=11 

FileVersion=1,0,0.1 

用浏览器调用ActiveX组件或者发布组件打包文件都需要 

用OBJECT元素。发布.CAB文件,需要在OBJECT元素的 

CODEBASE特性引用包含.INF文件的.CAB文件。当访问该 

【RegisterFiles 1 

%1 1%\DeanUSBKev.dll 

页面时,Interact Explorer将自动把.CAB文件作为软件分发单 

位下载并安装,每次访问时还会自动检测版本并进行更新。注 

其中“thiscab”是一个关键字,指包含该INF的CAB文 

件。也可以从网上下载所需要的DLL文件,只要指定一个 

Hq3"P网址即可,如: 

file—win32一x86=hRp://www。chengdulob。net/activex/ 

DeanUSBKey。DLL 

意,浏览器出于安全性考虑,会拦截未经数字认证的控件。修 

改浏览器设置,在“|nternet选项”一“安全”一“受信任的 

站点”一“站点”中添加服务器地址,不要选复选框“对该 

区域中的所有站点要求服务器验证”。解决浏览器拦截问题, 

而不用更改浏览器的安全级别。 

关键字“file—win32一x86”指定平台是x86。 

“FileVersion”为文件版本号。 

“DestDir”指的是装载目录或者文件的地址:1 1指系统目 

录WINDOWS/SYSTEM32;10指Windows目录。 

2.CAB打包 

Windows在系统目录中自带了CAB制作工具IExpress(、 

WINDOWS\system32、目录下)。打开IExpress: 

(1)选择“Create new Serf Extraction Directive file”,点击 

下一步。 

(2)选择“Create compressed files only(ActiveX In— 

六、结语 

程序在Windows Server 2003+Microsoft Visual Stu— 

dio.NET2005(c++)英文版环境下调试通过。组件技术得到越 

来越广泛的应用,而VC提供的活动模板库为我们创建功能强 

大的COM组件提供了很好的框架。通过ActiveX网页控件使网 

页也可以访问客户端的硬件资源。丰富B/S结构系统的功 

能。 

stalls)”,点击下一步。 

(3)点击Add,把文件(fi_nd_api.dll,DeanUSBKey.dll, 

duk

usbkey.inf)添加进去,点击下一步。 

_

参考文献: 

【1】WWW.vckbase.corn. 

【2】(美)Dale Rogerson,译者杨秀章.COM技术内幕~一微软 

组件对象模型.清华大学出版社. 

(收稿日期:2007年8月26日) 

(4)点击Browse,输入.CAB文件的存放地址(包含所取 

文件名),这里取TestCAB.CAB,并且要选中“Store ifles using 

Long File Name inside Package”,点击下一步。 


本文标签: 组件 文件 接口 系统 添加