`

Javascript调用ActiveX对象

    博客分类:
  • js
 
阅读更多
在学习的过程中,我发现下面两篇文章很有指导意义,代码基本是从第一篇文章拷贝而来。
        第一篇文章先写了一个DLL,这个DLL实现了求两个数之和的函数。接着实现了一个简单的ATL对象,通过该ATL对象调用DLL中实现的函数,最后在Javascript中调用该ATL对象相应的方法以求两个数之和。
       我想着扩展一下这个例子,在DLL中实现了一个函数以获取笔记本电脑电池电量的剩余时间,关于电池的信息,Windows提供了一个很方便的API-GetSystemPowerStatus供开发者使用,该API返回一个结构体如下:
typedef struct _SYSTEM_POWER_STATUS {
  BYTE ACLineStatus;
  BYTE BatteryFlag;
  BYTE BatteryLifePercent;
  BYTE Reserved1;
  DWORD BatteryLifeTime;
  DWORD BatteryFullLifeTime;
} SYSTEM_POWER_STATUS,  *LPSYSTEM_POWER_STATUS;
       通过MSDN可以查到结构体各字段的意义,这个例子中只用到了第五个字段用以获取电池的可持续时间(以秒为单位,当笔记本电脑直接接着交流电时会返回-1),当然也可以一次性返回整个结构体,不过这需要定义比较复杂的IDL类型,我想着返回简单int型比较简单,所以也就返回这一个值了。
       首先新建一个DLL工程,就取名为CalcImpl工程,然后新建一个dll.h和dll.cpp文件,在dll.h写入以下代码:
#ifndef _DLL_H_
#define _DLL_H_

#if defined DLL_EXPORT
#define DECLDIR _declspec(dllexport)
#else
#define DECLDIR _declspec(dllimport)
#endif

extern "C"
{
    DECLDIR int Add(int a, int b);
    DECLDIR int ShowBatteryLifeTime(void);
}

#endif
       在dll.cpp写入以下代码:
#include <windows.h>

#define DLL_EXPORT
#include "dll.h"

extern "C"
{
    DECLDIR int Add(int a, int b)
    {
        return (a + b);
    }

    DECLDIR int ShowBatteryLifeTime(void)
    {
        SYSTEM_POWER_STATUS SystemPowerStatus;
        GetSystemPowerStatus(&SystemPowerStatus);
        int BatteryLifeTime = SystemPowerStatus.BatteryLifeTime;

        return BatteryLifeTime;
    }
}
       Build会生成CalcImpl.lib和CalcImpl.dll文件。接着新建一个ATL Project,取名为CalcCtrl,完成之后会自动生成很多文件。接着为工程添加一个类,在对话框中选择"ATL Simple Object",在接下来的对话框中输入"MyTest",在Options中勾上"Support"多选框中的"Connection points"和"IObjectWithSite(IE object support)",点finish之后工程会生成MyTest对象,自动生成MyTest.h和MyTest.cpp等文件。然后选择类视图,右击"IMyTest"项,然后选择"Add"->"Add Method",在弹出的对话框中的"Method name"处填入"GetBatteryLifeTime",这个方法是最后供Javascript使用的。我发现这儿有一个奇怪的事情,在为方法名选择参数时,out和retval多选框始终都是灰色的,而in确实可以选上的。因为根据用户的选择会生成相关的代码,此处如果不能设置好返回类型,那么就必须手动修改一些文件了。CalcCtrl.idl文件中有接口的定义,接口的实现则放在MyTest.cpp中。编译CalcCtrl.idl文件居然不会对MyTest.h和MyTest.cpp做相应的修改,有点不方便。"GetBatteryLifeTime"只有一个int型的返回值,手动修改CalcCtrl.idl中该接口的声明如下:
GetBatteryLifeTime([out, retval]INT* out);
        对MyTest.h和MyTest.cpp也做相应的处理,因为两个文件中都是C++的代码,所以去掉[out, retval]便可。在MyTest.h头文件中添加以下两句:
#include "../CalcImpl/dll.h"                    //用于包含相关函数声明
#pragma comment(lib, "CalcImpl.lib") //隐式使用CalcImpl.dll所需要的    
        第一篇文章中直接通过LoadLibrary/GetProcAddress/FreeLibrary来使用CalcImpl.dll中的函数,这样太麻烦了,即要声明函数指针类型,又要注意释放句柄,不如通过隐式调用来使用CalcImpl.dll中的函数。在MyTest.cpp文件的CMyTest::GetBatteryLifeTime函数写入以下代码:
STDMETHODIMP CMyTest::GetBatteryLifeTime(INT* out)
{
     //只是简单地调用CalcImpl.dll中的函数
    *out = ShowBatteryLifeTime();

    return S_OK;
}
       build CalcCtrl工程将生成CalcCtrl.dll,不过会有如下的错误提示:
Project : error PRJ0050: Failed to register output.  Please try enabling Per-user Redirection or register the component from a command prompt with elevated permissions.
       VS似乎在尝试注册该组件,权限不够所以失败了,在一个普通的命令窗口使用regsvr32注册组件也会失败,如果使用管理员身份打开命令窗口就能成功注册该组件了。上面这个错误没有什么影响,因为注册是要交给浏览器自动完成的,这儿生成CalcCtrl.dll就好了。
       当网页中嵌入ActiveX对象时,浏览器会判断该对象是否已经存在,如果不存在将提示下载相关的资源,下载完成之后如何处置,这就需要一个inf文件来说明了。因此创建一个setup.inf文件,写入以下内容:
[version]
; version signature (same for both NT and Win95) do not remove
signature="$CHICAGO$"
AdvancedINF=2.0

[Add.Code]
CalcCtrl.dll=CalcCtrl.dll
CalcImpl.dll=CalcImpl.dll
setup.inf=setup.inf

[install.files]
CalcCtrl.dll=CalcCtrl.dll
CalcImpl.dll=CalcImpl.dll
setup.inf=setup.inf

[CalcCtrl.dll]
clsid={A83904E6-3288-431C-8213-8874E228990E}
file-win32-x86=thiscab
FileVersion=1,0,0,1
DestDir=11
RegisterServer=yes

[CalcImpl.dll]
file-win32-x86=thiscab
DestDir=11
FileVersion=1,0,0,1
RegisterServer=yes

[setup.inf]
file=thiscab

[RegisterFiles]
%11%\CalcCtrl.dll

; end of INF file
        "DestDir=11"表示将DLL下载到系统目录下(WINDOWS/SYSTEM32)。CalcImpl.dll、CalcCtrl.dll和setup.inf三件东西都准备好了之后就要开始打包了。打开一个cmd窗口,输入"iexpress",根据向导一步步做,最后生成一个calc.CAB文件。接着写一个测试网页,内容如下:
<HTML>
<HEAD>
<TITLE>Test ActiveX</TITLE>
<OBJECT ID="CalcCtrl" NAME="CalcCtrl"
 CODEBASE="calc.CAB#version=1,0,0,1"
 CLASSID="clsid:A83904E6-3288-431C-8213-8874E228990E">
 </OBJECT>
<script language="javascript">
function doTest()
{
    var leftTime = CalcCtrl.GetBatteryLifeTime();
    
    if(leftTime == -1)
    {
        alert("unknown");
    }
    else
    {
        var hours;

        //Javascript的'/'运算符并不会取整
        hours = leftTime / 3600;
    
        alert(hours + "hours");
    }
}
</script>

</HEAD>
<BODY>
<input type="button" value="Get left time" id="btnOK" onclick="doTest();"></input>
</BODY>
</HTML>
        上面用到的clsid可以在工程中的MyTest.rgs文件找到,这个文件中包含一些要写入注册表的信息,setup.inf中的那个clsid随便填似乎都可以,这个页面中的clsid就必须填正确了。使用IE浏览器打开该页面之后,会提示有不安全的内容,点击"允许阻止的内容"之后,会接连弹出两个对话框(这里是在单机环境进行测试的,在真实的网路环境下,可以还要配置下IE浏览器,让其运行未验证的ActiveX对象或者添加信任域),然后就可以在"WINDOWS/SYSTEM32"目录下发现CalcImpl.dll,CalcCtrl.dll这两个文件了。当笔记本接着交流电时,弹出的对话框将将提示"unknown",只有拔掉电源,不断刷新页面,过一会儿将显示电池的剩余使用时间。
        每次使用时都会弹出如下的对话框,很烦人。
Javas<wbr>cript调用ActiveX对象 - 绚丽也尘埃 - 处女地
        可以参看第二篇文章,将类MyTest从IObjectSafetyImpl派生可以解决这个问题。我还发现另外一个问题,如果使用下面的代码调用ActiveX对象:
MyTest = new ActiveXObject( "CalcCtrl.MyTest");
 
var sum = MyTest.GetBatteryLifeTime();
        浏览器并不会自动下载calc.CAB文件,所以页面运行将出错。但是如果组件已经被安装了,使用这种方法却又能正常工作。
分享到:
评论

相关推荐

    Javascript调用ActiveX对象.docx

    JavaScript调用ActiveX对象是一种在特定环境下,如Internet Explorer浏览器,使用JavaScript与ActiveX技术进行交互的方法。ActiveX是微软提出的一种技术,主要用于创建可插入Web页面的控件,提供丰富的用户界面和...

    调用activex控件读硬盘.rar_ 网页 ActiveX_ActiveX 网页_JAVASCRIPT 硬盘_activex

    JavaScript是一种广泛用于网页脚本的编程语言,它可以调用ActiveX对象,使得网页具备了与用户计算机更深度交互的能力,包括读取硬盘信息。 然而,这种技术在现代网络环境中已经逐渐被淘汰,主要是因为ActiveX只在IE...

    JavaScript调用Activex控件的事件的实现方法

    JavaScript调用ActiveX控件的事件的实现方法是客户端编程中的一个重要技巧,特别是在与旧版浏览器或特定系统交互时。ActiveX控件是微软的一种技术,允许在网页中嵌入可执行代码,常用于访问本地资源或提供特殊功能。...

    Html Js 调用 activex 控件 示例

    HTML和JavaScript调用ActiveX控件是Windows平台上一种常见的技术,尤其在早期的Web应用程序中,用于实现浏览器端与本地操作系统更深入的交互。ActiveX控件是由Microsoft开发的一种技术,允许开发者创建可嵌入到网页...

    javascript调用delphi中的函数

    标题“javascript调用delphi中的函数”涉及到的技术领域是跨语言通信,具体是JavaScript与Delphi之间的交互。这种交互通常发生在Web应用程序与桌面应用程序的集成,或者在浏览器扩展和本地资源之间。以下是对这一...

    调用activeX在对话框中显示网页

    在本案例中,“调用ActiveX在对话框中显示网页”是一个简洁且实用的方法,相比使用HTMLView控件,可能具有更高的灵活性和更少的复杂性。 首先,我们需要了解如何在VC++(Visual C++)环境中创建和使用对话框。...

    javascript发送邮件

    JMail的工作原理是,通过JavaScript调用ActiveX对象,设置发件人、收件人、主题、正文等信息,然后使用JMail.dll发送邮件。示例代码可能如下: ```javascript var jmail = new ActiveXObject("JMail.Message"); ...

    JavaScript 调用 C++ 生成的 DLL.pdf

    JavaScript 调用 C++ 生成的 DLL,DLL 使用 ATL 封装的 ActiveX 控件,仅支持 IE 浏览器。 本文档是对工程实现时的每一个步骤进行描述,大量截图,非常详细。 完整工程代码路径:...

    js调用activeX获取u盘序列号的代码

    在本文中,我们将探讨如何使用JavaScript调用ActiveX对象来获取U盘的序列号。ActiveX是Microsoft开发的一种技术,允许在Web浏览器中嵌入和运行各种控件,如读取和写入文件、访问硬件设备等。 首先,我们需要了解...

    java\JavaScript利用ActiveX导出Excel,Word .doc

    1. **JavaScript与ActiveX对象交互**: JavaScript可以通过创建ActiveXObject实例来访问和控制ActiveX控件。在本文中,我们看到了`new ActiveXObject("Excel.Application")`和`new ActiveXObject("Word.Application...

    Javascript调用本地播放器(potplayer)播放原画视频和音乐.zip

    PotPlayer可能提供了相应的ActiveX对象,使得JavaScript可以通过创建和调用该对象的方法来控制播放器的行为,例如播放、暂停、停止、快进、快退等。 文件“115fullspeed.user.js”和“115fullspeed.meta.js”可能是...

    Flex ActiveX通过JS相互调用.rar

    例如,可以创建一个函数`callActiveXMethod`,该函数接受参数并调用ActiveX对象的相关方法。 3. **Flex与JavaScript交互**: Flex通过Flash Player的ExternalInterface API与JavaScript进行通信。在Flex中,可以...

    activex与js交互

    1. **调用方式**:JavaScript可以通过`document.getElementById`获取ActiveX对象,然后通过该对象调用ActiveX控件的方法或属性,实现数据传递和功能调用。 2. **安全性策略**:由于安全原因,JavaScript访问ActiveX...

    ActiveX反射集成,方法事件调用.rar

    例如,一个JavaScript脚本可能需要调用由ActiveX控件提供的.NET方法。这通常通过COM互操作实现,使得JavaScript能够与ActiveX控件进行交互。JavaScript通过IDispatch接口发送消息到ActiveX控件,然后控件执行相应的...

    ATL ActiveX Opengl JavaScript

    项目可能包括ATL COM对象的实现,该对象封装了OpenGL的功能,并提供了一套供JavaScript调用的方法。 `Web`文件夹可能包含HTML、CSS和JavaScript文件,这些文件展示了如何在网页中嵌入和使用这个ActiveX控件。...

    JavaScript 调用 C++ 生成的 DLL

    JavaScript 调用 C++ 生成的 DLL,DLL 使用 ATL 封装的 ActiveX 控件,仅支持 IE 浏览器。 本资源为整套工程,编译 ATL_API 后,在Debug/Release目录下,使用 IE 打开TestJavaScript.html,点击“Add”按钮查看结果...

    Delphi 测试ActiveX与JavaScript的交互

    3. JScript ActiveX Automation:JScript,JavaScript的一个版本,支持ActiveX Automation,可以直接创建和操作ActiveX对象。 为了测试这种交互,我们可以创建一个简单的HTML页面,其中包含一个调用ActiveX控件的...

    JS_CPP.rar_JS调用C++_javascript VC_js调用C++函数_vc javascript_调用JS

    - 文件 `JSCallFromC++` 很可能包含一个示例,演示了如何设置 ActiveX 对象并从 JavaScript 调用其 C++ 实现的方法。 2. **C++ 调用 JavaScript 函数**: - C++ 可以通过嵌入浏览器引擎(如 IE 的 Trident 或者 ...

Global site tag (gtag.js) - Google Analytics