web上用Activex控件开发步骤(MFC)

首先要说明的是 web上用activex是门被抛弃的技术。为什么这么说,主要基于以下几个原因:

1. 功能过于强大,强大到一旦安装,他所具有的权限可以做任何事,极易被人利用做坏事(相信大家都有浏览网页后莫名被安装流氓软件的经历,当然流氓软件利用的方式不止控件一种);

2. 通过网页下载控件的中间过程受到操作系统、杀毒软件、浏览器等多方面因素限制,这使你的控件产品未必能在所有用户的电脑上正常使用;

3. 最恶心的一点,未签名没有正规安全证书的控件,在最新的浏览器上(IE7等)默认安全策略是直接屏蔽掉的,而你如果想要获取这个信任,需要向微软等少数单位申请,花费有多少?据说是每年4千多。。。

看了以上如果你还是想要知道步骤,如下:

一。用Vc++6.0新建工程里的向导创建MFC activeX controlWizard,细节不说了,根据你控件需要了,略有不同,问题不会太大。

二。你控件代码的主xx.cpp(非xxCtr.cpp)文件中添加安全接口函数,否则每次运行控件时IE都会给出安全提示,很烦!
#include"comcat.h"
#include"Objsafe.h"

// 本控件的CLSID,注册表用
const GUID CDECLCLSID_SafeItem ={ 0x7AE7497B, 0xCAD8, 0x4E66,
                     { 0xA5,0x8B,0xDD,0xE9,0xBC,0xAF,0x6B,0x61 } };
//
版本控制
const WORD _wVerMajor =1;
//
次版本号
const WORD _wVerMinor =0;


/
//CICCardApp::InitInstance - DLL initialization

BOOL CICCardApp::InitInstance()
{
    BOOLbInit = COleControlModule::InitInstance();

    if (bInit)
    {
    
    }

    return bInit;
}


//
//CICCardApp::ExitInstance - DLL termination

int CICCardApp::ExitInstance()
{
   return COleControlModule::ExitInstance();
}


//

// 创建组件种类
HRESULTCreateComponentCategory(CATID catid, WCHAR* 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\ComponentCategories\{..catid...}
    //key is registered.
   CATEGORYINFO catinfo;
   catinfo.catid = catid;
   catinfo.lcid = 0x0409 ; // english

    // Make sure the provided description is nottoo long.
    //Only copy the first 127 characters if it is.
    intlen = wcslen(catDescription);
    if(len>127)
       len = 127;
   wcsncpy(catinfo.szDescription, catDescription, len);
    //Make sure the description is null terminated.
   catinfo.szDescription[len] = '\0';

    hr = pcr->RegisterCategories(1,&catinfo);
       pcr->Release();

    return hr;
}

// 注册组件种类
HRESULTRegisterCLSIDInCategory(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;
}
//
卸载组件种类
HRESULTUnRegisterCLSIDInCategory(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 -Adds entries to the system registry
STDAPIDllRegisterServer(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);

    // 标记控件初始化安全.
    // 创建初始化安全组件种类
    hr =CreateComponentCategory(CATID_SafeForInitializing,
              L"Controls safely initializable from persistent data!");
    if(FAILED(hr))
       return hr;
    //
注册初始化安全
    hr =RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
    if(FAILED(hr))
       return hr;

    // 标记控件脚本安全
    // 创建脚本安全组件种类 
    hr =CreateComponentCategory(CATID_SafeForScripting, L"Controls safelyscriptable!");
    if(FAILED(hr))
       return hr;
    //
注册脚本安全组件种类
    hr =RegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
    if(FAILED(hr))
       return hr;

    return NOERROR;
}


//
// DllUnregisterServer -Removes entries from the system registry

STDAPI DllUnregisterServer(void)
{
   HRESULT hr;

    AFX_MANAGE_STATE(_afxModuleAddrThis);

    if (!AfxOleUnregisterTypeLib(_tlid, _wVerMajor,_wVerMinor))
       return ResultFromScode(SELFREG_E_TYPELIB);

    if(!COleObjectFactoryEx::UpdateRegistryAll(FALSE))
       return ResultFromScode(SELFREG_E_CLASS);

    // 删除控件初始化安全入口.
   hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForInitializing);
    if(FAILED(hr))
       return hr;
    //
删除控件脚本安全入口
   hr=UnRegisterCLSIDInCategory(CLSID_SafeItem, CATID_SafeForScripting);
    if(FAILED(hr))
       return hr;

//
   return NOERROR;
}

三。添加自己的代码到控件文件xxCtr.cpp中,这里最好通过向导添加View->ClassWard->automation。

四。编译生成你的xx.ocx控件文件,这个文件其实就是个DLL函数库,只是后缀不同而已。

五。制作xx.inf文件用于之后的空间打包压缩。红色部分为需要根据你自己情况修改的地方。
[version]   
signature="$CHICAGO$"   
AdvancedINF=1.0   
[Add.Code]   
xx.ocx=xx.ocx  
 
[xx.ocx]
   
file-win32-x86=thiscab   
clsid={351FC603-D784-4B8D-BA2C-33C212EC5BAA}   
FileVersion=1,0,0,1   
RegisterServer=yes
   

六。打包压缩成xx.cab文件。你需要用到给控件签名的一些工具:cabarc.exe、signcode.exe,另外你可能需要用于制作自己试验证书的工具:makecert.exe、cert2spc.exe。
制作根证书MyCert.cer和私钥myKey.PVK:
makecert -r  -sv "myKey.PVK"  -n CN="xx ElectricIndustry Co. Ltd."   MyCert.cer
CERT2SPC MyOKIcert.cer MyOKIcert.spc
打包压缩空间为xx.cab:
cabarc -s 6144 n xx.cab xx.ocx xx.inf
数字签名cab文件
双击signocode.exe文件,图形化签名,注意要通过自定义选择自己的证书和私钥而不是选择系统已有的。

七。在你要用空间的Web上添加代码:
             <tdcolspan="2"><object id='t1'codeBase=/UserMode/xx.cab#version=1,0,0,1 classid='clsid:F3530445-A287-4A0B-AC3E-C4AF2B63EBA7'height=0 width=0 ></object></td>

八。调用控件内方法。通过javascript直接调用控件对象的方法就行了,比如调用空间中存在的一个download()方法: document.getElementByID("t1").download();

八。客户端使用,其他人从网上下载到你的控件后,如果是Window XP系统的话,需要先导入证书为可信任(详细到Google上搜索导入证书,很容易),再安装控件,之后才能用;而如果是Window2000用户则只要安装控件就可以使用了。

九。控件的删除。Internet选项-〉设定-〉显示对象,直接看到你的xx.cab文件,Del掉就行了,注册表中信息会自动消除掉,当然你也可以直接到注册表中删除对应xx.inf中列出的键值的项。

十。升级。只要在源代码中更改xx.rc文件中对应的那些1.0.0.1为你的新版本号,并同时更改你调用控件的web上的版本号就可以了,下一次客户访问这个页面时会自动提示安装新控件,新控件会覆盖就版本的控件。

   以上仅供参考,本人也是新手,最近工作需要用控件才能完成一些功能,以上包含了我开发过程中碰到的诸多问题,希望对所有人能有所帮助

 

有人评论:

您的 STDAPIDllUnregisterServer(void) 在实际调用中,是会报错的,然后仔细看了下你的代码发现,你在调用删除控件初始化安全入口和删除控件脚本安全入口之前就先删除了控件,所以会报错,所以我给你换了下先后位置,这样就好了,如下: 
STDAPIDllUnregisterServer(void) 

HRESULT hr; 
AFX_MANAGE_STATE(_afxModuleAddrThis); 

// 删除控件脚本安全入口 
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem,CATID_SafeForScripting); 
if (FAILED(hr)) 

AfxMessageBox("删除控件脚本安全入口失败!",MB_ICONSTOP | MB_OK); 
return hr; 

// 删除控件初始化安全入口. 
hr=UnRegisterCLSIDInCategory(CLSID_SafeItem,CATID_SafeForInitializing); 
if (FAILED(hr)) 

AfxMessageBox("删除控件初始化安全入口!",MB_ICONSTOP | MB_OK); 
return hr; 

if(!AfxOleUnregisterTypeLib(_tlid, _wVerMajor, _wVerMinor)) 
returnResultFromScode(SELFREG_E_TYPELIB); 

if(!COleObjectFactoryEx::UpdateRegistryAll(FALSE)) 
returnResultFromScode(SELFREG_E_CLASS); 

// 
return NOERROR; 
}


-----------------------------------------------------------------------------------------------------------------------------------------

以上博客我忘记从哪儿转载的了,我实际用的代码如下:

1、创建文件 safecom.h,内容如下:


// description : 把Activex OCX注册为安全组件


#include "stdafx.h"


#include "comcat.h"
#include "Objsafe.h"


#ifndef __SAFE_COMPONENT__
#define __SAFE_COMPONENT__


HRESULT CreateComponentCategory(CATID catid, WCHAR* 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

    // Make sure the provided description is not too long.
    // Only copy the first 127 characters if it is.
    int len = wcslen(catDescription);
    if (len>127)
        len = 127;
    wcsncpy(catinfo.szDescription, catDescription, len);
// Make sure the description is null terminated.
catinfo.szDescription[len] = '\0';

    hr = pcr->RegisterCategories(1, &catinfo);
pcr->Release();

return hr;
}


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(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;
}


#define DllRegisterServer \
__DllRegisterServer(void);\
STDAPI DllRegisterServer(void)\
{/*MessageBox(0,"DllRegisterServer",0,0);*/\
__DllRegisterServer();\
HRESULT hr;\
hr = CreateComponentCategory(CATID_SafeForInitializing,L"Controls safely initializable from persistent data!");\
if (FAILED(hr))\
return hr;\
hr = RegisterCLSIDInCategory(__tlid,CATID_SafeForInitializing);\
if (FAILED(hr))\
return hr;\
hr = CreateComponentCategory(CATID_SafeForScripting,L"Controls safely scriptable!");\
if (FAILED(hr))\
return hr;\
hr = RegisterCLSIDInCategory(__tlid, CATID_SafeForScripting);\
if (FAILED(hr))\
return hr;\
return NOERROR;\
}\
STDAPI __DllRegisterServer






#define DllUnregisterServer \
__DllUnregisterServer(void);\
STDAPI DllUnregisterServer(void)\
{/*MessageBox(0,"DllUnregisterServer",0,0);*/\
HRESULT hr;\
hr=UnRegisterCLSIDInCategory(__tlid, CATID_SafeForInitializing);\
if (FAILED(hr))\
return hr;\
hr=UnRegisterCLSIDInCategory(__tlid, CATID_SafeForScripting);\
if (FAILED(hr))\
return hr;\
return __DllUnregisterServer();\
return NOERROR;\
}\
STDAPI __DllUnregisterServer


#endif // __SAFE_COMPONENT__ for end


2、在控件代码的主xx.cpp(非xxCtr.cpp)文件中添加

#include "safecom.h"


//本控件的CLSID,注册表用  红色部分为需要根据你自己情况修改的地方。

const GUID CDECL BASED_CODE __tlid =
{ 0x5E655EBA, 0x51F9, 0x4D27, { 0xB7, 0xF2, 0x72, 0xE4, 0x16, 0x4C, 0x1C, 0x3E } };


好像就是这些了,跟博客上的差不多。

-----------------------------------------------------------------------------------------------------------------------------------------

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值