一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

用ATL開發(fā)和部署ActiveX網(wǎng)頁控件

 十指緊ㄣ扣 2010-07-29


一、前言

B/S結(jié)構(gòu)的系統(tǒng)中,出于安全性考慮一般不準(zhǔn)許瀏覽器訪問客戶端的硬件資源,如控制打印機(jī),照相機(jī)等。對于一個(gè)完善系統(tǒng)來說,往往很多時(shí)候又需要控制這些資源。通過在瀏覽器中插入ActiveX插件是一種很好的解決方式。

在實(shí)際的項(xiàng)目開發(fā)中,遇到系統(tǒng)登錄需要增加物理身份識(shí)別。即在系統(tǒng)登錄的時(shí)候,除了要驗(yàn)證用戶名和密碼外,還需要驗(yàn)證硬件USB KEY上的信息。具體業(yè)務(wù)流程為:客戶端程序讀取用戶硬件USB KEY里的個(gè)人信息(即加密認(rèn)證信息),提交給認(rèn)證服務(wù)器進(jìn)行認(rèn)證,認(rèn)證服務(wù)器通過身份識(shí)別后,業(yè)務(wù)系統(tǒng)通過解析返回的XML信息判斷用戶是否合法有效,建立起用戶和業(yè)務(wù)系統(tǒng)的信任通道。讀取硬件USB KEY的信息我們通過本例的ActiveX控件來完成。硬件USB KEY選用飛天誠信的ePass1000ND產(chǎn)品。

二、概念

1、ActiveX控件

ActiveXMicrosoft提出的一組使用COMComponent Object Model,組件對象模型)使得軟件組件在網(wǎng)絡(luò)環(huán)境中進(jìn)行交互的技術(shù)集。它與具體的編程語言無關(guān)。作為針對Internet應(yīng)用開發(fā)的技術(shù),ActiveX被廣泛應(yīng)用于WEB服務(wù)器以及客戶端的各個(gè)方面。

ActiveX是從Microsoft的復(fù)合文檔技術(shù)—OLE成長起來的。其基本的出發(fā)點(diǎn)是想讓某個(gè)軟件通過一個(gè)通用的機(jī)構(gòu)為另一個(gè)軟件提供服務(wù),可以將其插入到WEB網(wǎng)頁或其它應(yīng)用程序中。在Internet上的使用,ActiveX特點(diǎn)是:一般軟件需要用戶單獨(dú)下載然后執(zhí)行安裝,而ActiveX插件是當(dāng)用戶瀏覽到特定的網(wǎng)頁時(shí),IE瀏覽器即可自動(dòng)下載并提示用戶安裝。 但安裝的一個(gè)前提是必須經(jīng)過用戶的同意及確認(rèn)。

2COM技術(shù)

COMMicrosoft組件對象模型的簡稱。是一個(gè)說明如何建立可動(dòng)態(tài)交替更新組件的規(guī)范。它提供了客戶和組件為保證能夠互操作應(yīng)該遵循的標(biāo)準(zhǔn)。該標(biāo)準(zhǔn)對于組件架構(gòu)的重要性同其他任何一個(gè)具有可交替更新部分的系統(tǒng)是一樣的。

COM標(biāo)準(zhǔn)包括規(guī)范和實(shí)現(xiàn)兩大部分,規(guī)范部分定義了組件和組件之間通信的機(jī)制,這些規(guī)范不依賴于任何特定的語言和操作系統(tǒng),只要按照該規(guī)范,任何語言都可以使用;COM標(biāo)準(zhǔn)的實(shí)現(xiàn)部分是COM庫,COM庫為COM規(guī)范的具體實(shí)現(xiàn)提供了一些核心服務(wù)。

COM模型中,對象本身對于客戶來說是不可見的,客戶請求服務(wù)時(shí),只能通過接口進(jìn)行。一般接口是不會(huì)改變的。

3、ATL技術(shù)

ATLActive Template Library)是微軟的活動(dòng)模板庫,是一個(gè)產(chǎn)生C++/COM代碼的框架,專門用于開發(fā)COM組件。ATL提供了小巧、高效、靈活的類,這些類為創(chuàng)建可互操作的COM組件提供了基本的設(shè)施。ATL完全面向COM組件,其結(jié)構(gòu)完全針對COM中的諸多規(guī)范。是編寫COM組件的快捷工具。

三、實(shí)現(xiàn)

1、項(xiàng)目

打開Visual Studio.Net 2005,建立一個(gè)解決方案或項(xiàng)目DeanUSBKey。在項(xiàng)目類型中選擇Visual C++下的ATL選項(xiàng),在模板中選擇”ATL Project”,項(xiàng)目名為DeanUSBKey。點(diǎn)擊確定,系統(tǒng)就在指定的目錄下建立了DeanUSBKey項(xiàng)目和解決方案。

點(diǎn)擊確定后,會(huì)出現(xiàn)建立ATL項(xiàng)目向?qū)υ捒?,引?dǎo)用戶快捷方便的建立ATL項(xiàng)目。點(diǎn)擊下一步,進(jìn)入項(xiàng)目屬性設(shè)置對話框,如圖1所示。可以通過該對話框選擇是否屬性化和發(fā)布方式等。


1 項(xiàng)目屬性設(shè)置對話框

具體選項(xiàng)說明如下:

Attributed 即屬性化,支持屬性化編程,是未來的發(fā)展方向,是IDL方案的一種替代方案。

Dynamic-link library(DLL) 即動(dòng)態(tài)鏈接庫,表示建立一個(gè) DLL 的組件程序。

Executable(EXE) 即可執(zhí)行文件,表示建立一個(gè) EXE 的組件程序。

Service(EXE) 即服務(wù),表示建立一個(gè)系統(tǒng)服務(wù)組件程序,系統(tǒng)啟動(dòng)后就會(huì)加載并執(zhí)行的程序。

Allow merging of proxy/stub code 即允許合并代理/存根代碼,選擇該項(xiàng)表示把“代理/存根”代碼合并到組件程序中,否則需要單獨(dú)編譯,單獨(dú)注冊代理存根程序。

Support MFC 即支持 MFC,建議不要選擇,除非有特殊的原因,比如我們原來的程序是基于MFC的,我們的組件必須要MFC的支持。一般在寫 ATL 程序,不選擇該項(xiàng)。但是很多VC程序員對于MFC的數(shù)據(jù)集合類和字符串類依賴很大,建議采用STL中的相關(guān)類進(jìn)行替代。具體替換方案:

1std::string代替MFC中的CString;

2std::vector代替MFC的數(shù)組類如CArray,CPtrArray等;

3、std::list替換MFC中的CList等列表類;

4、對于BSTR建議采用CComBSTR 類,或_bstr_t類,本例子中就會(huì)用到該類;

Support COM+1.0 支持事務(wù)處理的 COM+ 功能。

    我們選擇如圖1所示的選項(xiàng),點(diǎn)擊完成。ATL Project項(xiàng)目就生成好了,系統(tǒng)會(huì)在指定目錄下生成一系列文件,ReadMe.txt里有各文件的文件說明。尤其要注意接口定義語言文件(DeanUSBKey.idl),它描述了對象的接口細(xì)節(jié)。

2、組件

   COM模型中,客戶請求服務(wù)時(shí),是通過接口和組件進(jìn)行交互的?,F(xiàn)在還是一個(gè)空的ATL項(xiàng)目,還沒有任何組件。

添加組件,也就是添加ATL對象類。在DeanUSBKey項(xiàng)目上點(diǎn)擊右鍵,添加類,彈出對話框。在類別中選擇ATL。在模板中選擇“ATL Simple Object”即ATL簡單對象。點(diǎn)擊確定,出現(xiàn)建立組件向?qū)АH鐖D2所示,在Short Name輸入組件名稱USBKey,其它內(nèi)容系統(tǒng)會(huì)自動(dòng)填寫。注意組件名稱不能和項(xiàng)目名稱重名。點(diǎn)擊下一步進(jìn)入組件選項(xiàng)設(shè)置界面。如圖3所示


2 ATL簡單對象組件名字對話框


3 ATL簡單對象組件選項(xiàng)對話框

具體選項(xiàng)說明如下:

Threading model 即線程模型,COM中的線程,這是一個(gè)復(fù)雜的部分。我們選"單元"(Apartment),它代表當(dāng)在線程中調(diào)用組件函數(shù)的時(shí)候,這些調(diào)用會(huì)排隊(duì)進(jìn)行。如果想了解詳細(xì)細(xì)節(jié)可以參看《COM技術(shù)內(nèi)幕》一書。

Interface 即接口,雙重(Dual),雙重接口表示在一個(gè)接口中,同時(shí)支持自定義接口和 IDispatch 接口。這個(gè)非常重要,為了能夠使組件能夠在腳本中使用,必須選擇雙重接口選項(xiàng)。因?yàn)槟_本語言的解釋器只認(rèn)識(shí) IDispatch 接口。自定義接口(Custom),直接實(shí)現(xiàn)的是IUnknown接口。

Aggregation 即聚合,寫的組件,將來是否允許被其他人以聚合方式(有聚合和包容兩種方式)使用。Only(只能創(chuàng)建為聚合),有點(diǎn)類似 C++Java 中的不能直接創(chuàng)建實(shí)例的虛類,如果不是處于設(shè)計(jì)目的,一般這個(gè)選項(xiàng)不用。大多數(shù)情況下支持“聚合”,所以我們選擇“Yes”。

ISupportErrorInfo 是否支持豐富信息的錯(cuò)誤處理接口。

Connection points 即連接點(diǎn),是否支持連接點(diǎn)接口(事件、回調(diào))。

IObjectWithSite 是否支持IE的調(diào)用。

我們選擇如圖3所示的選項(xiàng),點(diǎn)擊完成。USBKey的組件建立完成。在生成的USBKey.cpp里將是接口IUSBKey的實(shí)現(xiàn)。

3、接口方法

在類視圖中,IUSBKey接口上點(diǎn)擊鼠標(biāo)右鍵。在添加項(xiàng)里有添加方法和屬性,選擇添加方法。打開圖4所示的添加接口方法對話框。添加接口方法GetContent,并添加接口方法的參數(shù)。[in]表示參數(shù)方向是輸入;[out]表示參數(shù)方向是輸出;[out,retval]表示參數(shù)方向是輸出,同時(shí)可以作為函數(shù)運(yùn)算結(jié)果的返回值。一個(gè)函數(shù)中,可以有多個(gè)[in]、[out],但[retval]只能有一個(gè),并且要和[out]組合后在最后一個(gè)位置。詳細(xì)的定義說明可以參考IDL的語法說明。

 

4 添加接口方法對話框

USBKey.cpp文件里添加函數(shù)GetContent的具體實(shí)現(xiàn)過程。核心代碼如下:

STDMETHODIMP CUSBKey::GetContent(LONG lFlags, BSTR* pUSBContent)

{  

EPAS_STATUS retval;//狀態(tài)

    EPAS_HANDLE epsHandle ; //EPAS句柄

// 創(chuàng)建設(shè)備句柄

retval = epas_CreateContext(&epsHandle,0,EPAS_API_VERSION);//調(diào)用EPASAPI函數(shù)訪問USB Key硬件

    if (FT_SUCCESS != retval)  

    {return ReturnError(retval);}//返回相應(yīng)的錯(cuò)誤

    // 打開設(shè)備

    retval = epas_OpenDevice(epsHandle,lFlags,(void *)szAppID);

    if (FT_SUCCESS != retval)

    {return ReturnError(retval);}

    //得到序列號(hào)

    unsigned long sn[2] = {0};

    retval = epas_GetProperty(epsHandle,EPAS_PROP_SERNUM,NULL,sn,sizeof(sn));

    if (FT_SUCCESS != retval)  

    {return ReturnError(retval);} 

    char m_sn [8*1024+17]={0};

    sprintf_s(m_sn, "%08X%08X", sn[1], sn[0]);//16進(jìn)制打印到字符串m_sn

    //得到加密字符串

    //1、登錄

    char s[80] = "1234";//登錄密碼

    retval = epas_Verify(epsHandle,EPAS_VERIFY_USER_PIN,(unsigned char*)s,4);

    if (FT_SUCCESS != retval){return ReturnError(retval);}

    //2、打開文件

   EPAS_FILEINFO epsFileInfo = {0};

    unsigned long epsFileID = 0x1234;//文件編號(hào)

    retval = epas_OpenFile(epsHandle,0,epsFileID,&epsFileInfo,sizeof(epsFileInfo));

    if (FT_SUCCESS != retval){return ReturnError(retval);   }

    //3、讀取文件內(nèi)容

    unsigned long rLen = 0;

    unsigned char rBuff[8*1024] = {0};

    ZeroMemory(rBuff,8*1024);

    retval = epas_Read(epsHandle,0,0,rBuff,epsFileInfo.ulFileSize,&rLen);

    if (FT_SUCCESS != retval){return ReturnError(retval);}

    //4、關(guān)閉文件

retval = epas_CloseFile(epsHandle);

//關(guān)閉設(shè)備,刪除Context

retval = epas_CloseDevice(epsHandle);

retval = epas_DeleteContext(epsHandle);

    strcat_s(m_sn,(char*)rBuff);

    *pUSBContent=_com_util::ConvertStringToBSTR((char *)r_sn);

    return S_OK;

}

    為了能在函數(shù)中使用USBKey廠家提供的訪問函數(shù)和使用BSTR類,需在stdafx.h頭文件里面引入相應(yīng)的.h.lib文件。如下:

#include "FT_ND_API.h"http:// ePass1000ND的接口頭文件

#include "comutil.h"

#pragma comment(lib, " FT_ND_API.lib")

#pragma comment(lib, "comsuppw.lib")

   如果編譯通過,VS.Net IDE會(huì)打開窗口選擇執(zhí)行控件的外部文件。選擇regsvr32。編譯成功后,組件會(huì)自動(dòng)注冊??梢栽谙到y(tǒng)組件服務(wù)里面查看剛注冊的組件DeanUSBKey。

4、錯(cuò)誤處理

COM方法通過返回HRESULT來報(bào)告錯(cuò)誤,其他信息異??梢酝ㄟ^ IErrorInfo 接口提供給客戶端,這里主要講述HRESULT返回COM方法錯(cuò)誤。

HRESULT由一個(gè) 32 位代碼組成。分為四部分,如下:

Field

Severity

Reserved

Facility

Code

Bit(s)

31

29-30

16-28

0-15

各字段說明:

Severity 字段是其中最重要的一個(gè)。當(dāng)一個(gè)方法返回時(shí)若該字段被設(shè)置了值,就說明發(fā)生了一個(gè)錯(cuò)誤。該字段使所有的 COM 錯(cuò)誤代碼顯示為負(fù)的十進(jìn)制整數(shù)。

Reserved 字段目前是預(yù)留字段。

Facility 字段為錯(cuò)誤類別代碼,總共表示 8192 種錯(cuò)誤,由一個(gè)集中的機(jī)構(gòu)負(fù)責(zé)分配這些種類。

Code 字段提供了一個(gè)可容納 65536 個(gè)代碼的空間。具體的錯(cuò)誤代碼就在該字段里面體現(xiàn)。

在讀取USBKey信息時(shí),捕獲的錯(cuò)誤做處理,以COM錯(cuò)誤的形式拋出。即把前16位改為0x80FF,代碼如下:

LONG CUSBKey::ReturnError(LONG retval)

{ return 0x80FF0000+retval;}

5、實(shí)現(xiàn)IObjectSafety接口

ActiveX控件的編寫到此就可以結(jié)束了,但我們在瀏覽器使用改控件的過程中,經(jīng)常都會(huì)彈出現(xiàn)在運(yùn)行的腳本不安全的提示。如果給客戶使用,將會(huì)帶來極大不便。怎么解決呢,可以通過實(shí)現(xiàn)IObjectSafety接口來解決。ATL 在類 IObjectSafetyImpl 中提供了此接口的實(shí)現(xiàn)。如果瀏覽器發(fā)現(xiàn)你的控件支持 IObjectSafety,就在導(dǎo)入控件之前調(diào)用 IObjectSafety::SetInterfaceSafetyOptions 方法來確保安全性腳本操作。就不會(huì)彈出提示對話框。

USBKey.h文件里繼承類列表的末尾(class ATL_NO_VTABLE CUSBKey)加入如下語句:    public IObjectSafetyImpl<CUSBKey, INTERFACESAFE_FOR_UNTRUSTED_CALLER| INTERFACESAFE_FOR_UNTRUSTED_DATA>,

并在COM 映射里添加一下行(黑體部分)

BEGIN_COM_MAP(CUSBKey) 

    COM_INTERFACE_ENTRY(IObjectSafety)

END_COM_MAP()

四、測試

    在網(wǎng)頁里通過腳本語言調(diào)用ActiveX控件DeanUSBKey??梢酝ㄟ^VBScriptJAVAScript來調(diào)用。為了能在腳本語言里使用控件接口,需知道接口的classid,可以查看接口的注冊表腳本文件USBKey.rgs找到classid值。調(diào)用代碼為:

<object classid="clsid: 4F3320E4-4B66-4C85-8538-6E17699AAB46" id="Dean" name = "Dean" ></object>

<form id="form1" name="form1" method="post" action="">

   <a href="#" onclick="return CallUSB();">js調(diào)用ActiveX測試</a>

   <input id="Write" name="Write" type="button" value="vb調(diào)用ActiveX測試" />

</form>

<SCRIPT LANGUAGE="JavaScript">

<!—

//JavaScript調(diào)用Demo

 function CallUSB()

 {

try {

 var USBContent = Dean.GetContent(0);

alert(USBContent);

 } catch (e) {

    alert("錯(cuò)誤號(hào): " + e.number );

 }  

 return false;

 }

//-->

</SCRIPT>

<script language="VBScript" type="text/vbscript">

‘VBScript調(diào)用Demo

Sub Write_OnClick

On Error Resume Next

USBContent = Dean.GetContent(0)

MsgBox USBContent

MsgBox (err.number and &hff)

End Sub

</script>

五、部署

Internet軟件分發(fā)單位是軟件包,它由包含.INF文件或軟件分發(fā).OSD文件(或兩者都包括)的.CAB文件所組成。一個(gè)分發(fā)單位也可以包含軟件組件,如ActiveX控件,DLL文件等。

1、Inf文件編寫

INF文件是一個(gè)文本文件,指定運(yùn)行控件所需要下載或者呈交的文件(比如.DLL或者其它.OCX)。一個(gè).INF文件就捆綁了.CAB壓縮文件所有的必須文件。 缺省情況下,與現(xiàn)有硬盤中文件版本號(hào)相同的文件不被下載。INF文件如下:

[version]

signature="$CHICAGO$"

AdvancedINF=2.0

[Add.Code]

FT_ND_API.dll=FT_ND_API.dll

DeanUSBKey.dll=DeanUSBKey.dll

[FT_ND_API.dll]

file-win32-x86=thiscab

DestDir=11

FileVersion=1,0,6,413

[DeanUSBKey.dll]

file-win32-x86=thiscab   

RegisterServer=yes

clsid={4F3320E4-4B66-4C85-8538-6E17699AAB46}

DestDir=11   

FileVersion=1,0,0,1

[RegisterFiles]

%11%\DeanUSBKey.dll

說明:

"thiscab" 是一個(gè)關(guān)鍵字,指包含該INFCAB文件。也可以從網(wǎng)上下載所需要的DLL文件,只要指定一個(gè)HTTP 網(wǎng)址即可,如:

file-win32-x86=http://www./activex/DeanUSBKey.DLL

關(guān)鍵字"file-win32-x86"指定平臺(tái)是x86。

"FileVersion"文件版本號(hào)。

"DestDir"指的是裝載目錄或者文件的地址: 11指系統(tǒng)目錄 WINDOWS/SYSTEM32;10 Windows 目錄。

2、Cab打包

Windows在系統(tǒng)目錄中自帶了CAB制作工具IExpress\WINDOWS\system32\目錄下)。打開IExpress

1)選擇“Create new Self Extraction Directive file”,點(diǎn)擊下一步。

2)選擇“Create compressed files only(ActiveX Installs)”,點(diǎn)擊下一步。

3)點(diǎn)擊Add,把文件添加(ft_nd_api.dll,DeanUSBKey.dll, duk_usbkey.inf)添加進(jìn)去,點(diǎn)擊下一步。

4)點(diǎn)擊Browse,輸入.CAB文件的存放地址(包含所取文件名),這里取TestCAB.CAB,并且要選中 “Store files using Long File Name inside Package”。點(diǎn)擊下一步。

5)選擇“Don’t save”,一直點(diǎn)擊下一步,直到完成。

3、自動(dòng)安裝

用瀏覽器調(diào)用ActiveX組件或者發(fā)布組件打包文件都需要用OBJECT元素。發(fā)布.CAB文件,需要在OBJECT元素的CODEBASE特性引用包含.INF文件的.CAB文件。當(dāng)訪問該頁面時(shí),Internet Explorer將自動(dòng)把.CAB文件作為軟件分發(fā)單位下載并安裝,每次訪問時(shí)還會(huì)自動(dòng)檢測版本并進(jìn)行更新。注意,瀏覽器出于安全性考慮,會(huì)攔截未經(jīng)數(shù)字認(rèn)證的控件。修改瀏覽器設(shè)置,在Internet選項(xiàng)-〉安全-〉受信任的站點(diǎn)-〉站點(diǎn) 中添加服務(wù)器地址,不要選復(fù)選框“對該區(qū)域中的所有站點(diǎn)要求服務(wù)器驗(yàn)證”。解決瀏覽器攔截問題,而不用更改瀏覽器的安全級別。

六、結(jié)束語

  程序在Windows Server 2003+Microsoft Visual Studio.NET2005(C++)英文版環(huán)境下調(diào)試通過。組件技術(shù)得到越來越廣泛的應(yīng)用,而VC提供的活動(dòng)模板庫為我們創(chuàng)建功能強(qiáng)大的COM組件提供了很好的框架。通過ActiveX網(wǎng)頁控件使網(wǎng)頁也可以訪問客戶端的硬件資源。豐富B/S結(jié)構(gòu)系統(tǒng)的功能。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    欧美一区二区三区播放| 国产一级精品色特级色国产| 国产欧美日韩在线一区二区| 91人妻久久精品一区二区三区| 国产成人精品视频一区二区三区| 欧美日韩亚洲国产精品| 中国一区二区三区不卡| 成年人视频日本大香蕉久久| 国产美女精品午夜福利视频| 黄片免费在线观看日韩| 午夜国产精品福利在线观看| 亚洲精品偷拍一区二区三区| 日本久久精品在线观看| 在线观看免费视频你懂的| 老司机亚洲精品一区二区| 在线中文字幕亚洲欧美一区| 国产日产欧美精品视频| 色哟哟国产精品免费视频| 精品伊人久久大香线蕉综合| 精品香蕉国产一区二区三区 | 精品人妻精品一区二区三区| 日韩黄色一级片免费收看| 日韩欧美综合中文字幕| 日本丰满大奶熟女一区二区| 国产成人精品一区在线观看 | 亚洲国产成人精品福利| 亚洲成人免费天堂诱惑| 国产激情国产精品久久源| 自拍偷拍一区二区三区| 国产又长又粗又爽免费视频| 免费在线成人激情视频| 国产成人精品视频一二区| 久久热在线免费视频精品| 少妇人妻一级片一区二区三区| 精品伊人久久大香线蕉综合| 99久只有精品免费视频播放 | 国产日韩久久精品一区| 欧美日韩国产成人高潮| 91天堂免费在线观看| 亚洲国产精品一区二区毛片| 欧美成人久久久免费播放|