vc6<实用>开发activex并发布全攻略(二)(初级篇)

[背景]

       做过ActiveX控件的朋友都知道,要想把自己做的ActiveX控件功能放在自己的网页上使用,那么用户在客户端就必须进行本地的注册,也就是说用户得首先要把该ActiveX控件(test.ocx)放在本机的%system%/system32下,然后运行DOS工具里面运行regsvr32 test.ocx命令进行注册。但如果真是这么去做的话,那么代表着你处于危险之中了,因为您是通过让用户自己去部署设置环境来达到你的目的,这就失去软件项目本身所存在的价值。那么面对这种情况,我们应该如何解决呢?聪明的你一定会很快就想到,我们可以使用户在客户端自动下载安装该ActiveX控件,这样一来即可以实现我们所想要的功能,又不需要用户自己去部署设置环境,这岂不是一举两得。

[必备条件]

一、用于将ActiveX控件进行打包并加数据鉴名的工具集:

makecert.exe 制作cer格式的证书,即X.509证书,同时可以创建私钥和公钥。

cert2spc.exe  将cer格式证书转换成spc格式证书,即PKCS #7证书。

cabarc.exe   将ocx打包成cab。

signcode.exe 将证书签署到ocx上去。

chktrust.exe  检查签署证书后的ocx是否正确。

certmgr.exe  是管理证书用的。

二、用于进行打包用的ocx控件evS1300.ocx。

三、用于查看ocx控件的工具ActvxDoc。

[制作过程]

一、环境设置

1、下载makeCAB包,解压到本地目录(如E盘根目录),如查看到如图1所示的工具集,则表示已下载成功:

(图1:makeCAB包的工具集)

 

2、设置系统环境变量,右键单击“我的电脑”à选择“属性”à选择“高级”选项卡,打开如图2所示的系统属性面版块:

 

 

 

(图2:系统属性版块)

 3、在系统属性版块里单击“环境变量(N)”按钮,打开图3:

 

 

(图3:系统变量)

       4、选择“系统变量(S)”里的“新建(W)”按钮,打开“编辑系统变量”对话框,如图4所示,然后在“变量值(V)”里加入“;E/makeCAB”:

(图4:编辑系统变量)

二、将用于打包的OCX控件放在E盘根目录下(本文档使用名为evS1300.ocx的控件来进行介绍),如图5所示,其中evS1300.ocx是本文档进行操作的控件对象,而mfc71.dll、msvcp71.dll、msvcr71.dll这三个文件通常是进行打包时一并打包的文件,但不是必须(推荐一起打包),其可在系统中的system32目录下找

到,请自行准备。

 

 

(图5;用于操作的OCX控件路径)

三、ActiveX发布步骤

1、单击“开始”à“动行(R)”à输入“cmd”à回车à进入到操作的控件所在的目录,如图6所示:

(图6:进入E:/evS1300目录)

2、创建PVK文件(私人密匙文件),在命令行中输入“makecert -sk evS1300 evS1300.pvk -n CN=XXXXXXX公司”,然后回车,如图7所示:

(图7:创建PVK文件)

     3、创建CER文件(公司证书),在命令行中输入“makecert -sk evS1300.pvk evS1300.cer”,然后回车,如图8所示,若出现“Successed”提示,则会在E:/evS1300目录下生成evS1300.cer文件,如图9所示:

(图8:创建CER文件)

(图9:生成evS1300.cer)

     4、创建SPC测试软件出版商证明书,在命令行中输入“cert2spc evS1300.cer evS1300.spc”,然后回车,如图10所示:

 

(图10:创建SPC测试软件出版商证明书)

       5、创建INF文件,用记录本编辑以下信息

  1. [version]      
  2. signature="$CHINA$"     
  3. AdvancedINF=1.0     
  4.      
  5. [Add.Code]      
  6. evS1300.ocx=evS1300.ocx      
  7. msvcr71.dll=msvcr71.dll      
  8. mfc71.dll=mfc71.dll      
  9. msvcp71.dll=msvcp71.dll      
  10.      
  11. [evS1300.ocx]      
  12. file=thiscab      
  13. clsid={0440906E-9BD6-4F3E-B65A-39E1B339D9DA}      
  14. FileVersion=1,0,0,0     
  15. RegisterServer=yes      
  16.      
  17. [msvcr71.dll]      
  18. file-win32-x86=thiscab      
  19. RegisterServer=no      
  20. DestDir=11     
  21. FileVersion=7,10,3052,4     
  22.      
  23. [mfc71.dll]      
  24. file-win32-x86=thiscab      
  25. RegisterServer=no      
  26. DestDir=11     
  27. FileVersion=7,10,3077,0     
  28.      
  29. [msvcp71.dll]      
  30. file-win32-x86=thiscab      
  31. RegisterServer=no      
  32. DestDir=11     
  33. FileVersion=7,10,3077,0     

     如图11所示,并保存为E:/evS1300/evS1300.inf,如图12所示

(图11:evS1300.inf)

 

(图12:保存evS1300.inf)

       在evS1300.inf的内容里,[version][Add.Code]项是必须的,[Add.Code]的键值项的多少取决于以下你所配制项的多少。[msvcr71.dll][mfc71.dll][msvcp71.dll]就是上面我所说不是必须的项,只要你想把msvcr71.dllmfc71.dllmsvcp71.dll包括在发布包里,那这么三项就必须写在inf里,而这三项的具体内容是固定的,可复制过去即可。最为关键的就是[evS1300.ocx]项,其中有clsidFileVersion就是evS1300.ocxclassIdversion,这要求必须一至,否我们发布出去的CAB包时不能在客户端自动更新下载安装。说到这里,那我们如何才能知道evS1300.ocx里面的classIdversion呢?我在上面的必备条件里介绍到有一个用于查看ocx控件的工具ActvxDoc,对,就是用它,我们双击这个文件运行它,此时可以看到图13所示的界面: 

 

(图13:ActiveX Documenter)

在图13的界面里,点击“File”à“Open…”,打开您所要查看的OCX控件,如图14所示:

 

 

(图14:打开控件)

打开了控件之后,我们在界面的右边部位“Class”的下拉框里选择“<all interfaces=""></all>”就可以看到我们想要查找的FileVersionclassId,如图15所示:

 

 

(图15:控件属性)

       6、创建CAB文件,在命令行中输入“cabarc -s 6144 n evS1300.cab msvcr71.dll mfc71.dll msvcp71.dll evS1300.ocx evS1300.inf”,然后回车,如图16所示:

 

 

(图16:创建CAB文件)

       7、使用Code Signing Wizard签署一个CAB文件,首先双击运行工具集里面的signcode.exe(或在命令行里直接输入“signcode”后回车),系统会弹出如图17所示的数字签名向导:

 

 

(图17:数字签名向导)

  8、单击“下一步(N)”按钮,来到图18所示,选择要进行数字签名的且已做成CAB包的文件evS1300.cab文件。

(图18:选择CAB包)

9、选择好CAB包后单击“下一步(N)”按钮,在选择想要的签名类型里选择“自定议(C)”并单击“下一步(N)”按钮,如图19所示:

(图19:选择签名类型)

       10、接下来单击“从文件选择(F)”按钮,选择刚刚制作的evS1300.cer,如图20所示:

(图20:选择CER证书)

       11、在图20中单击“下一步(N)”按钮来到图21,然后在图21里选择“CSP中的私钥(K)”。

 

(图21:选择私钥的位置)

       12、在图21中单击“下一步(N)”按钮,然后在图22中的散列算法中选择“shal”,并单击“下一步(N)”按钮。

(图22:选择散列算法)

       13、在“证书路径中的证书”中选择“证书路径中的所有证书,包括根证书(C)”,在“其它证书(可选)”中选择“包括在以下PKCS #7 证书(.p7b)文件中的证书(P):”,并单击“浏览(R)…”按钮选择evS1300.spc文件,选择完后单击“下一步(N)”按钮,如图23所示:

(图23:选择其它证书)

       14、接下来在弹出的“数据描述”窗口中输入公司的名称和网址并单击“下一步(N)”按钮,如图24所示:

(图24:输入数据描述)

       15、现大部份工作都已完成,在接下来的一步当中是可选的操作,其作用只是为CAB加入时间戳,此步骤完全可以不做,如图25所示:

(这里我提拱三个免费的代码签名时间戳地址)

VeriSign:  http://timestamp.verisign.com/scripts/timstamp.dll

Comodo:  http://timestamp.comodoca.com/authenticode

GeoTrust/TrustCenter: http://www.trustcenter.de/codesigning/timestamp

(图25:给数据盖时间戳)

       16、完成,在图25中单击“下一步(N)”按钮便可来到数字签名向导的最后一步,即操作总览,如图26所示,单击“完成”按钮便可大功告成,如图27所示:

 

(图26,完成操作总览)

(图27:签名成功提示)

 

呵呵,不要以为这样发布就会成功。

博文中说用工具查看我们自己开发的ActiveX控件GUID,但我的好像查看不了。

其实我们在vc工程中就能查看到。双击DMyActiveX接口类,

 

找到       [ uuid(743F39F2-E3A5-4550-A203-4A1CFAE9ABCF),

         helpstring("MyActiveX Control"), control ]

       coclass MyActiveX

       {

              [default] dispinterface _DMyActiveX;

              [default, source] dispinterface _DMyActiveXEvents;

       };

 

方法中743F39F2-E3A5-4550-A203-4A1CFAE9ABCF就是我们ActiveX的GUID.

 

 

还有一种方法就是打开VC的工具OLEView,懒的敲字了,看图吧:

 

我的MyActiveX.inf如下:

   [version]  

   signature="$CHINA$" 

   AdvancedINF=1.0 

     

   [Add.Code]  

   MyActiveX.ocx=MyActiveX.ocx  

   msvcr71.dll=msvcr71.dll  

   mfc71.dll=mfc71.dll  

   msvcp71.dll=msvcp71.dll

   

  [MyActiveX.ocx]  

   file=thiscab  

  clsid={743F39F2-E3A5-4550-A203-4A1CFAE9ABCF}  

  FileVersion=1,0,0,0 

  RegisterServer=yes  

    

  [msvcr71.dll]  

  file-win32-x86=thiscab  

  RegisterServer=no  

   DestDir=11 

  FileVersion=7,10,3052,4 

    

  [mfc71.dll]  

  file-win32-x86=thiscab  

  RegisterServer=no  

   DestDir=11 

  FileVersion=7,10,3077,0 

    

  [msvcp71.dll]  

  file-win32-x86=thiscab  

  RegisterServer=no  

   DestDir=11 

  FileVersion=7,10,3077,0 

 

按照上面的方法,用cabarc -s 6144 n MyActiveX.cab msvcr71.dll mfc71.dll msvcp71.dllMyActiveX.ocx MyActiveX.inf命令制作好MyActiveX..cab。

文件目录:

 

我们来写个测试页面,代码如下:

 

<object id='test1'codeBase='http://10.79.108.108/MyActiveX.cab#version=1,0,0,0' classid='clsid:743F39F2-E3A5-4550-A203-4A1CFAE9ABCF ' height=0 width=0 ></object>

<script>

      a=test1.test(2,1);

      alert(a);

</script>

注意:链接IP改成你机子的IP

将它保存为test.html格式存放到IIS下,同时把MyActiveX也拷贝到IIS下,也就是C:\Inetpub\wwwroot下。

打开页面测试下:

http://10.79.108.108/test.html

弹出对话框:

 

选择是:

 

呵呵,弹出计算值3。算是成功了一半。那为什么系统没有提示下载控件呢?这是因为VS在编译的时候已经帮我们把控件注册到系统中了。

那现在首要的问题,就是先解决上面那个是否允许activex运行的提示框。

在网上查了下资料,说是要实现ISafeObject接口。那好,我们下面就来实现:打开工程,找到CMyActiveXCtr类,双击打开文件:

 

在文件中添加引用:

#include "comcat.h"

#include "Objsafe.h"

两个头文件。

并在DECLARE_DYNCREATE(CMyActiveXCtro)后添加如下代码:

DECLARE_INTERFACE_MAP()

      BEGIN_INTERFACE_PART(ObjSafe, IObjectSafety)

      STDMETHOD_(HRESULT, GetInterfaceSafetyOptions) (

              /* [in] */ REFIID riid,

              /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,

              /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions

      );

        

      STDMETHOD_(HRESULT, SetInterfaceSafetyOptions) (

              /* [in] */ REFIID riid,

              /* [in] */ DWORD dwOptionSetMask,

              /* [in] */ DWORD dwEnabledOptions

      );

      END_INTERFACE_PART(ObjSafe);

效果如图:

 

在工程目录中切换到FileView模式,打开MyActiveXCtrl.cpp文件,

然后将以下代码添加到构造函数CMyActiveXCtrl:: CMyActiveXCtrl ()上面,CMyActiveXCtrl替换为你的控件名称:

/

// Interface map forIObjectSafety

 

BEGIN_INTERFACE_MAP(CMyActiveXCtrl, COleControl )

INTERFACE_PART(CMyActiveXCtrl,IID_IObjectSafety, ObjSafe)

END_INTERFACE_MAP()

 

/

// IObjectSafety memberfunctions

 

// Delegate AddRef, Release,QueryInterface

 

ULONG FAR EXPORTCMyActiveXCtrl::XObjSafe::AddRef()

{

   METHOD_PROLOGUE(CMyActiveXCtrl, ObjSafe)

    returnpThis->ExternalAddRef();

}

 

ULONG FAR EXPORTCMyActiveXCtrl::XObjSafe::Release()

{

   METHOD_PROLOGUE(CMyActiveXCtrl, ObjSafe)

    returnpThis->ExternalRelease();

}

 

HRESULT FAR EXPORTCMyActiveXCtrl::XObjSafe::QueryInterface(

    REFIID iid,void FAR* FAR* ppvObj)

{

   METHOD_PROLOGUE(CMyActiveXCtrl, ObjSafe)

    return(HRESULT)pThis->ExternalQueryInterface(&iid, ppvObj);

}

 

const DWORD dwSupportedBits =

INTERFACESAFE_FOR_UNTRUSTED_CALLER|

INTERFACESAFE_FOR_UNTRUSTED_DATA;

const DWORD dwNotSupportedBits= ~ dwSupportedBits;

 

/

//CStopLiteCtrl::XObjSafe::GetInterfaceSafetyOptions

// Allows container to querywhat interfaces are safe for what. We're

// optimizing significantly byignoring which interface the caller is

// asking for.

HRESULT STDMETHODCALLTYPE

CMyActiveXCtrl::XObjSafe::GetInterfaceSafetyOptions(

/* [in] */ REFIID riid,

       /* [out] */ DWORD __RPC_FAR *pdwSupportedOptions,

       /* [out] */ DWORD __RPC_FAR *pdwEnabledOptions)

{

METHOD_PROLOGUE(CMyActiveXCtrl,ObjSafe)

 

HRESULT retval =ResultFromScode(S_OK);

 

// does interface exist?

IUnknown FAR* punkInterface;

retval =pThis->ExternalQueryInterface(&riid,

     (void* *)&punkInterface);

if (retval != E_NOINTERFACE) {// interface exists

punkInterface->Release();// release it--just checking!

}

 

// we support both kinds ofsafety and have always both set,

// regardless of interface

*pdwSupportedOptions =*pdwEnabledOptions = dwSupportedBits;

 

return retval; //E_NOINTERFACE if QI failed

}

 

/

//CStopLiteCtrl::XObjSafe::SetInterfaceSafetyOptions

// Since we're always safe,this is a no-brainer--but we do check to make

// sure the interfacerequested exists and that the options we're asked to

// set exist and are set on(we don't support unsafe mode).

HRESULT STDMETHODCALLTYPE

CMyActiveXCtrl::XObjSafe::SetInterfaceSafetyOptions(

       /* [in] */ REFIID riid,

       /* [in] */ DWORD dwOptionSetMask,

       /* [in] */ DWORD dwEnabledOptions)

{

   METHOD_PROLOGUE(CMyActiveXCtrl, ObjSafe)

 

// does interface exist?

IUnknown FAR* punkInterface;

pThis->ExternalQueryInterface(&riid,(void * *)&punkInterface);

if (punkInterface) { //interface exists

punkInterface->Release();// release it--just checking!

}

else { // interface doesn'texist

returnResultFromScode(E_NOINTERFACE);

}

 

// can't set bits we don'tsupport

if (dwOptionSetMask &dwNotSupportedBits) {

returnResultFromScode(E_FAIL);

}

 

// can't set bits we dosupport to zero

dwEnabledOptions &=dwSupportedBits;

// (we already know there areno extra bits in mask )

if ((dwOptionSetMask &dwEnabledOptions) !=

   dwOptionSetMask){

return ResultFromScode(E_FAIL);

}       

 

// don't need to changeanything since we're always safe

return ResultFromScode(S_OK);

}

效果如下图,注意画红框的地方:

 

F7编译以后,按前面的步骤重新发布。

打开测试页面http://10.79.108.108/test.html,呵呵那个讨厌的对话框消失了。

现在这个ActiveX是完全做好了,下一步我们来看看怎样让用户下载安装。

先在本地电脑测试:

因为我们用VC编译时,VC已经帮我们把ActiveX注册到系统中了,所以我们想看到下载安装画面,先必须删除注册信息。

打开运行窗口,输出regedit命令,查找我们的控件GUI: 743F39F2-E3A5-4550-A203-4A1CFAE9ABCF

 

我这里找到三项,那全部删除。

在打开测试页面之前,我们还得做个工作,就是设置IE安全。打开IE工具->Internet选项,如果是局域网,设置本地Intrance,允许下载未签名和已签名的ActiveX。如果是外网,方法一样。

 

现在打开测试页http://10.79.108.108/test.html

 

成功弹出下载ActiveX对话框。

点击安装,程序正常运行。OK,我们已经成功了一半。

 

上面只是在本地测试成功。现在在其他计算机上访问测试页,不要忘了IE的安全设置。打开页面后也是弹出上面的安装界面。可是,点安装后,程序无法正常运行。而且每次刷新页面,安装对话框总是弹出,很是郁闷。

经过Baidu,又找到了方法。原来是其他计算机上没有安装我们activeX运行所需的库文件。那我们就想办法让用户把这用到的DLL全部下载。

那首先得知道我们的activeX用到了哪些库。如下图,打开VC的工具Depends

 

选择我们的MyActiveX.ocx控件,如下图:

 

那我们可以看到我们用到的DLL有6个,一般Kernel32.DLL和OLEAUT32.DLL文件每个操作系统都有,所以剩下的4个DLL,在你机子上全盘搜索,找到这4个dll后将他们放入你的MyActiveX.ocx相同文件夹下,编辑MyActiveX.inf, 这些dll的版本信息FileVersion可以在此dll上点击右键->属性中得到:

   [version]  

   signature="$CHINA$" 

   AdvancedINF=1.0 

     

   [Add.Code]  

   MyActiveX.ocx=MyActiveX.ocx  

   msvcr71.dll=msvcr71.dll  

   mfc71.dll=mfc71.dll  

   msvcp71.dll=msvcp71.dll

   MFC42D.dll=MFC42D.dll  

   MSVCRTD.DLL=MSVCRTD.DLL

   gdi32.dll=gdi32.dll

   MFCO42D.DLL=MFCO42D.DLL

 

  [MyActiveX.ocx]  

  file=thiscab  

  clsid={743F39F2-E3A5-4550-A203-4A1CFAE9ABCF}  

  FileVersion=1,0,0,0 

  RegisterServer=yes  

    

  [msvcr71.dll]  

  file-win32-x86=thiscab  

  RegisterServer=no  

   DestDir=11 

  FileVersion=7,10,3052,4 

    

  [mfc71.dll]  

  file-win32-x86=thiscab  

  RegisterServer=no  

   DestDir=11 

  FileVersion=7,10,3077,0 

    

  [msvcp71.dll]  

  file-win32-x86=thiscab  

  RegisterServer=no  

   DestDir=11 

  FileVersion=7,10,3077,0 

 

  [MFC42D.dll]  

  file-win32-x86=thiscab  

  RegisterServer=no  

   DestDir=11 

  FileVersion=6.0.9782.0

 

  [MSVCRTD.DLL]  

  file-win32-x86=thiscab  

  RegisterServer=no  

   DestDir=11 

  FileVersion=6.0.9782.0

 

  [gdi32.dll]  

  file-win32-x86=thiscab  

  RegisterServer=no  

   DestDir=11 

  FileVersion=5.2.3790.2542 

 

  [MFCO42D.DLL]  

  file-win32-x86=thiscab  

  RegisterServer=no  

   DestDir=11 

   FileVersion=6.0.9782.0

保存后文件目录如下:

                                                      

用 cabarc-s 6144 n MyActiveX.cab msvcr71.dll mfc71.dll msvcp71.dll MFC42D.dllMSVCRTD.DLL gdi32.dll MFCO42D.DLL MyActiveX.ocx MyActiveX.inf

命令生成MyActiveX.cab文件。

在其他计算机上打开测试页。安装ActiveX成功,并且运行正常。

就此,一个简单的ActiveX发布成功了。

后面,我们还将对我们的ActiveX增加新的功能。敬请关注。

呵呵,好累啊~~~~

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值