zoukankan      html  css  js  c++  java
  • 浏览器插件之ActiveX开发(四)----web页面调用ActiveX

    转自:http://www.cnblogs.com/qguohog/archive/2013/01/25/2876828.html 

        简单总结一下前几篇文章的内容,《浏览器插件之ActiveX开发(一)》简单介绍了一下如何在Vs.net 2008下用C++开发基于MFC的ActiveX插件,《浏览器插件之ActiveX开发(二)》介绍了开发插件时可能遇到的问题,《浏览器插件之ActiveX开发(三)》介绍了如何注册插件以及如何打包成cab文件。但是,到目前为止还没有专门提及如何在Web页面中调用插件,本文主要针对这个问题进行展开。

    一、用<Object>标签调用ActiveX

        1、Object标签基本用法

        在Html页面中调用ActiveX插件最简单常用的方法是:

    1.  
      <object id="CardAccessor"
    2.  
      classid="clsid:03AD53E8-D7E7-485D-A39A-D07B37DEFBC9"
    3.  
      width="0"
    4.  
      height="0">
    5.  
      </object>

      id属性就不用解释了,和html中其他元素的id一样,是DOM树中各元素的唯一标识。width和height表示该ActiveX在Web页面中占位的大小,对于仅提供接口无UI界面的ActiveX来说将其设置为0即可,因为不需要在页面上显示任何内容(对于需要显示界面的ActiveX,需要在项目里创建Dialog及写相应逻辑,可以参考“A Complete ActiveX Web Control Tutorial”实例 )。

        classid属性在这里是一个非常关键的属性,IE正是通过他才能正确找到要调用的ActiveX的。每个ActiveX均有一个唯一的id来表示,这就是classid,在我们创建MFC ActiveX Control项目时Vs.net 2008就帮我们生成了这个id, 可以在程序的.idl文件最下方找到这个ID值:

                 image

         一般不建议手动修改程序中的这个uuid值,因为在xxxxCtrl.cpp文件中也用到了这个id值,只是表现形式不一样罢了:

                image

          控件注册成功后,这个classid及控件文件位置等信息均写入注册表了,如下所示:

                image

          当然,如果ActiveX还定义了其他属性,也可以在<object>中以属性的形式给他们赋值。

          如果用户的计算机已经注册了该插件(例如通过Setup.exe方式),那么Html引用上段代码后就可以通过js调用插件的接口和属性了(再次提示一下,ActiveX只能在IE浏览器运行,也就是<object…>这段代码在firefox等其他浏览器是不能正常工作的)。   


    1.  
      <fieldset>
    2.  
      <legend>Read Card No Testing</legend>
    3.  
      卡号:<input type="text" id="txtCardNo_Read" maxlength="32" class="txt disable" readonly />
    4.  
      <input type="button" id="btnRead" value=" Read CardNo " class="btn" οnclick="javascript:readCardNo();" />
    5.  
      </fieldset>
    6.  
       
    7.  
      <fieldset>
    8.  
      <legend>Write Card No Testing</legend>
    9.  
      卡号:<input type="text" id="txtCardNo_Write" maxlength="32" class="txt" />
    10.  
      <input type="button" id="btnWrite" value=" Write CardNo " class="btn" οnclick="javascript:writeCardNo();" />
    11.  
      </fieldset>
    12.  
       
    13.  
      <script type="text/javascript">
    14.  
      var txtCardNo_Read = document.getElementById("txtCardNo_Read");
    15.  
      var txtCardNo_Write = document.getElementById("txtCardNo_Write");
    16.  
      var objCard = document.getElementById("CardAccessor");
    17.  
       
    18.  
      function readCardNo() {
    19.  
      txtCardNo_Read.value = "";
    20.  
       
    21.  
      try{
    22.  
      var ret = objCard.ReadCardNo();
    23.  
       
    24.  
      if (ret == 0) {
    25.  
      txtCardNo_Read.value = objCard.CardNo;
    26.  
      alert("读卡成功!");
    27.  
      }
    28.  
      else {
    29.  
      alert("读卡失败!错误码为:" + ret);
    30.  
      }
    31.  
      }
    32.  
      catch (e) {
    33.  
      alert(e.message)
    34.  
      }
    35.  
      }
    36.  
       
    37.  
      function writeCardNo() {
    38.  
      var cardNo = txtCardNo_Write.value;
    39.  
       
    40.  
      try {
    41.  
      objCard.CardNo = cardNo;
    42.  
      var ret = objCard.WriteCardNo();
    43.  
       
    44.  
      if (ret == 0) {
    45.  
      alert("写卡成功!");
    46.  
      }
    47.  
      else {
    48.  
      alert("写卡失败!错误码为:" + ret);
    49.  
      }
    50.  
      }
    51.  
      catch (e) {
    52.  
      alert(e.message)
    53.  
      }
    54.  
      }
    55.  
       
    56.  
      </script>

    1.  
      <script type="text/javascript">
    2.  
      var objCard = document.getElementById("CardAccessor");
    3.  
       
    4.  
      if (objCard.object==null) {
    5.  
      alert("CardAccessor插件未安装!");
    6.  
      }
    7.  
      else{
    8.  
      alert("已检测到CardAccessor插件!");
    9.  
      }
    10.  
      </script>

    1.  
      <script type="text/javascript">
    2.  
      var objCard = document.getElementById("CardAccessor");
    3.  
       
    4.  
      if (objCard.CardNo==undefinedl) {
    5.  
      alert("CardAccessor插件未安装!");
    6.  
      }
    7.  
      else{
    8.  
      alert("已检测到CardAccessor插件!");
    9.  
      }
    10.  
      </script>


      3、如何让IE自动下载安装插件并智能升级

           如果检测到插件没有安装,怎样让IE自动从指定位置下载插件并自动安装呢?很简单,在object标签中使用codebase属性即可:


    <object id="CardAccessor" 
        classid="clsid:03AD53E8-D7E7-485D-A39A-D07B37DEFBC9" 
        codebase="CardAccessor.cab#version=1,0,0,1"
        width="0" 
        height="0">
    </object>

         codebase的值格式为“xxxxx.cab#version=1,0,0,1”。'#'前面部分为cab文件的位置,可以是在服务器上的绝对位置,也可以是相对位置。'#‘后面部分表示当前引用的cab包的版本号。当IE检测到系统没有注册指定插件,便从codebase指定的位置下载该cab到本地,并按照其中.inf文件的描述将各文件复制到指定位置并注册指定的控件。(注:在实际应用中涉及签名问题,后文再述)

         即使本地已经注册了该插件,IE还将拿已注册的控件版本号与codebase中指定的版本号相比较,如果codebase中指定的版本号大于已注册插件的版本号,IE仍然会从codebase指定位置下载cab包并重新注册该插件。

         正如前面的文章所提,为方便管理,一般将cab包中需注册的ocx文件的版本号视同cab版本号。

         当插件或插件依赖的文件需要升级时,只需更新相应的文件,并对.inf中的相应文件版本升级(为方便管理,无论是否更新了ocx文件,该ocx文件的版本号也跟着升级,因为其版本号代表了整个cab),然后重新打包成cab发布到服务器上,并更新html中object标签中codebase属性值的version部分版本号。当用户下次访问该页面时,IE将自动下载升级后的cab并重新注册插件。实际上,经过我的测试,及时服务器上的cab包不做任何变化,只要增加codebase中version的值,对应插件均会重新下载和注册。

    二、通过javascript的new ActiveXObject来调用ActiveX

          如果不使用object标签,也可以直接通过js的ActiveXObject来创建指定ActiveX的实例从而达到调用插件接口的目的(IE下xmlhttpRequest的调用就是这个原理)。例如:

    var objCard = new ActiveXObject("Uprain.CardAccessorCtrl.1");

          如果插件已经注册,接下来就可以通过objCard来调用插件接口和访问属性了。

          ActiveXObject函数的参数为对应插件的ProgId而非CLASSID。在项目中xxxxCtrl.cpp文件中同样可以找到或修改对应插件的ProgId值,如下图:

           image

         即IMPLEMENT_OLECREATE_EX的第二参数就表示当前插件的ProgId,该值可以根据实际需要自行修改。实际上,在注册表中通过ProgId是可以找到对应的ClassId的,两者是有关联的:

            image

          那么如何判断ActiveX是否已经安装呢?实际上如果ActiveX未安装,通过new ActiveXObject的方式来创建插件对象是会抛出“Automation 服务器不能创建对象”异常的。所以用如下方式即可:

    1.  
      try {
    2.  
      objCard = new ActiveXObject("Uprain.CardAccessorCtrl.1");
    3.  
      }
    4.  
      catch (e) {
    5.  
      alert("调用ActiveX失败!");
    6.  
      }

       不过,我在实际测试过程中遇到两种情况:

         1) 出现“Automation 服务器不能创建对象”异常的并不一定就表示插件没安装,也有可能是因插件未实现初始化或脚本安全接口,从而被IE拦截,需要调整IE“工具-选项-安全-自定义级别”中“ActiveX控件和插件”部分的设置;

         2) 有时候,同样已注册的插件,通过object标签引用的方式能正常调用接口,但通过new ActiveXObject的方式则调用插件接口失败。

  • 相关阅读:
    Nginx流量拷贝
    Nginx基于站点目录和文件的URL访问控制
    Nginx禁止ip访问或非法域名访问
    Nginx动静分离
    Nginx隐藏式跳转(浏览器URL跳转后保持不变)
    Harbor镜像仓库(含clair镜像扫描)
    Pod的QoS服务质量等级
    Pod容器应用"优雅发布"
    Pod容器自动伸缩(HPA) 测试
    NFS双机热备高可用环境
  • 原文地址:https://www.cnblogs.com/turnip/p/13151262.html
Copyright © 2011-2022 走看看