站内搜索: 请输入搜索关键词

当前页面: 开发资料首页Javascript 专题使用JavaScript中的OLE Automation

使用JavaScript中的OLE Automation

摘要: 使用JavaScript中的OLE Automation


  在前面的教程中我们已经有提到JavaScript中的OLE Automation。在本节的教程中,我们将一起来讨论一下JavaScript是怎样利用Automation的强大功能来扩展服务端脚本的能力的。

实际上Automation并不是新的事物。它已经在好几年前就流行了,但是被ActiveX脚本语言的支持是一个新的应用。如果你已经有了Visual Basic 或者Visual C++的编程背景,本节教程将介绍怎样利用你的经验来创建有用的脚本以控制外部的应用程序。

在你的脚本中控制外部的应用是非常强大的,比如从你的脚本中打开一个Word文档或者一个Excel电子表格。HTML编辑器,比如HomeSite 4.0和HotMetal Pro 6为你提供了丰富的工具使得你可以利用它们到你的主页中去。它们都是封装到ActiveX控件中的。本教程的内容主要有:

什么是Automation

什么是绑定

怎样创建Automation对象的新实例

怎样检索一个Automation对象存在的实例

怎样处理应用程序的实例

怎样提高脚本程序的性能

怎样处理集对象

从下一篇开始,我们对以上的内容逐个介绍。

使用JavaScript中的OLE Automation

什么是Automation

OLE(对象连接和嵌入)Automation允许应用程序完成通讯、交换数据以及控制其它应用程序等等。它还允许一个客户应用程序通过使用暴露对象的界面来创建和控制一个对象。一个Automation对象是可以通过Automation界面暴露给其它应用程序或者编程工具的一个对象。

Automation提供了一个文档案的、标准的方法来创建和访问应用程序。通常,Automation跟Visual Basic是紧密联系的。它有为C/C++开发人员提供了创建可编程的应用程序的强大工具,并且让Visual Basic设计人员访问和操作这些应用程序。这些C/C++程序员提供专业化的用户界面的解决方案并且给Visual Basic程序员提供了从应用程序组件中汇集定制解决方案的一种可靠的方法。

不仅Visual Basic 可以利用Automation,实际上,可编程的对象也可以任何的宏语言或者执行Automation的编程工具来进行访问。用户可以根据当前的知识选择一个编程工具,而不是为每一个应用程序学习新的语言。即使脚本语言,比如VBScript和Jscript页支持Automation 。

控制一个Automation应用程序的关键在于对应用程序的对象模型要有一个较好的理解。每一个应用程序的对象模型是不同的。微软现在声称在Office 程序组中每一个应用程序的每一个函数都可以通过应用程序的对象模型被程序员访问。这个Office程序组通过它的对象模型暴露了成千上万的对象、方法以及属性给程序员。这个消息对程序设计人员来说无疑是一个好消息。

但是,学习特殊应用程序的对象模型通常是很困难的,因为缺少描述各种软件对象的相关资料文档。微软的Office应用程序,比如在网上为程序员提供了许多资料文档,但是还有许多其它的应用程序不提供必须的文档。

在Microsoft Visaul Basic中的对象浏览器将对象、方法、属性以及外部Automation对象的常量展现在对话框中。这个工具同样适用于脚本设计中,因为应用程序的全局常量在脚本环境中不是有效的。如果你利用Automation来编写脚本,你可以适用对象浏览器来取出必需的常量的值,这样你就可以在脚本中来显性指定它们了。

2. 什么是绑定

在你适用一个对象模型的属性、方法和事件之前,你必需首先创建一个计划性的引用给包含了你想适用的属性、方法或者事件的类。你可以通过声明一个局部对象变量以保留一个引用给这个对象来实现这个目的。然后,你要为局部变量指定一个对象的应用。

VB和VBScript使用CreateObject()函数,来实现在Jscript使用这个ActiveXObject()构造函数的时候为一个Automation对象允许并返回一个引用。

实际上,绑定是指Visual Basic代码访问在其它的应用程序对象的方法。当你从一个应用程序使用Automation来处理另外一个应用程序中对象的时候,你编写Visaul Basic代码的应用程序就是一个Automation控制器。这个你正在处理对象的应用程序是Automation服务器。当一个Automation控制器创建一个指向由Automation服务器提供对象的变量,Visual Basic 必需验证对象是否存在以及使用对象的任何属性和方法是正确指定的。这个验证过程就所谓的”绑定”。有两种Visual Basic程序开发人员使用的绑定类型要注意: late binding(迟绑定) 和 early binding(早绑定)。

迟绑定

迟绑定是发生在运行时间并且比早绑定要慢。在迟绑定Automation代码中,Visual Basic在每次执行包括那个对象的行代码时必需查询对象以及它的方法和属性。为了验证这个对象以及它的方法和属性是否正确指定,Visual Basic 必需利用操作系统和支持对象的应用来检查。下面看看一段Visual Basic 代码:

Dim wdApp As Object

Set wdApp = CreateObject("Word.Application")

这个wdApp变量被定义为一般类型的对象。当这个变量被声明了,Visual Basic 并不知道它是属于什么类型的对象,所以你必须要为这个对象留出一定量的内存。既然特定对象引用是被指定到普通变量的,所以应用程序没有办法知道对象的界面是由什么组成的。只有在运行时间,应用程序才绑定到用户界面上。因此,不管你是什么时候引用新的对象,Visual Baisc必须检查系统注册以获得对象的信息。

早绑定

早绑定是一个解决慢Automation性能的好的解决方法。早绑定发生在编译的时候而不是在运行的时候,所以如果你的代码是在编译阶段保存的,在代码运行之前已经绑定结束了。当使用早绑定,Visual Basic 不需要连续验证对象信息,而是在应用程序执行的过程中使用对象。

另外,不是所有的Automation服务器都支持早绑定。这个Automation服务器必须支持一个类型库,这个类型库包含了关于服务器对象、方法和属性的信息。为了利用早绑定,你必须为Automation服务器的类型库设置一个引用。Visual Basic装载类型库到内存中,这使得它可以识别这些对象并且在代码编译的时候绑定它们。以下的代码段显示了怎样为对象创建一个早绑定界面:

Dim wdApp As Word.Application

Set wdApp = CreateObject("Word.Application")

3. 怎样创建Automation对象的新实例

Jscript(微软版本的JavaScript)是一个宽松类型的语言。换句话说,变量不是明显定义为指定的数据类型。你不能声明一个变量为指定的对象类型,所以早绑定不可能在JScript中。Jscript的ActiveXObject()构造函数通常用于为对象创建一个迟绑定界面:

var wdApp; // 一个普通变量

wdApp = new ActiveXObject("Word.Application");

Jscript不需要明显的变量声明,所以我们可以使用以下的代码:

var wdApp = new ActiveXObject("Word.Application");

ActiveXObject()函数的一般的语法如下:

var objVar = new ActiveXObject(class[, servername]);

objVar指定为一个持有实例化对象引用的变量。class使用library.object语法,它是指应用程序的名字(比如Word或者Excel等等)或者包含对象的库,并且对象是要创建的对象类的类型。servername(这是一个可选的参数)指定了包含对象的服务器的名字。

这个ActiveXObject()构造函数创建了一个OLE Automation(ActiveX)对象的实例。一旦对象被创建了,你可以使用定义的对象变量来引用它。如果ActiveX对象的实例已经运行,ActiveXObject()在它创建了必需的类型的对象的时候可能开始一个新的实例。下面的代码段可以让用户直接打开一个Word文档:

var pause = 0;

var wdDialogFileOpen = 80;

var wdApp = new ActiveXObject("Word.Application");

var dialog = wdApp.Dialogs(wdDialogFileOpen);

var button = dialog.Show(pause);
使用JavaScript中的OLE Automation

3. 怎样创建Automation对象的新实例

前面的代码段引用了Word.Application对象,它的方法在后面的教程要介绍。这里要注意等级结构,即一个方法或者属性是一个对象,它们又又自己的方法和属性。

象Visual Basic 6,Jscript可以通过增加一个新的参数(servername)来一步增加ActiveXObject函数。你可以在注册的ActinveX对象上指定服务器的名字。在远程服务器创建一个对象可以在Internet安全检查程序关闭的时候完成。你可以通过传递计算机的名字给ActiveXObject()构造函数的servername参数来在远程网络计算机上创建一个对象。比如,如果一个网络共享命名为"\\MYSERVER\D\Program Files",那那么servername的数值就为’MYSERVER”。另外,你可以使用DNS格式或者一个IP地址来指定位置。下面的函数返回运行在远程网络计算机(名为"MYSERVER")Word的实例的版本号:

function getVersion() {

var wdApp = new ActiveXObject("Word.Application", "MYSERVER");

return wdApp.Version;

}

如果指定的远程服务器不存在或者没有找到就会产生一个错误。当我们测试这个函数的时候,我们可以发现Jscript忽视了servername参数。所以我们在VBScript将这些函数放在一起,可以发现它并不工作:

Function GetVersion

Dim wdApp

Set wdApp = CreateObject("Word.Application", "MYSERVER")

GetVersion = wdApp.Version

End Function

4.怎样检索一个Automation对象存在的实例

Jscript支持同样Visual Basic中的GetObject()函数。它的一般的语法如下:

var objVar = GetObject([pathname][, class]);

objVar指定了一个变量来保留实例化对象的引用。Pathname是完全的路径和包含ActiveX对象的文件名。Class指定在字符串的表单中对象的类。Class参数使用了语法library.object,这跟ActiveXObject函数的第一参数是一样的。

总得说来,GetObject()函数在一个指定的文件中访问ActiveX 服务器。虽然两个参数是可选的,但是至少要提供其中一个参数。GetObject()函数是在存在ActiveX对象的当前实例的时候使用的。它不创建一个新的实例,比如ActiveXObject()函数。

如果你指定一个空的字符窗(""),GetObject()就返回一个对象的新实例,除非对象被注册为单一的实例,在这种情况下,当前的实例被返回。但是,如果pathname没有指定,对象的当前实例被返回。如果pathname没有被指定就会产生一个错误,并且没有对象的当前实例被发现。这里注意,GetObject()函数不能用于获得由Visual Basic创建的类的引用。

一些应用允许你访问对象库的特别部分。这时要在文件名之后使用一个感叹号(!),紧接下来的字符串是识别你想激活的库的一些部分。为了得到怎样创建这个字符串的信息,你可以参见Automation服务器的技术文档。比如,在画图引用程序中的文件可能拥有几个图层。你可以使用以下的代码来在一个图片中(比如 SCHEMA.CAD)激活一个图层:

var objVar = GetObject("C:\\CAD\\SCHEMA.CAD!Layer2");

一些文件(其它的库)可能支持更多的类。比如,一个画图文件可能支持三种不同的类:应用程序对象、画图对象以及工具条对象。既然你只可以引用单一的对象,所以你必须指定你指的是哪个类:

var objVar = GetObject("C:\\DRAWINGS\\SAMPLE.DRW", "Figment.Drawing");

在前面的例子种,Figment是一个画图应用程序的名字,而Drawing是其中一个它支持的对象类型。

5. 怎样处理应用程序的实例

文档模板是应用程序和它支持的文档之间的连接。文档模板有两种类型:单一文档,它只能一次打开一个类型的文档;多文档模板,它允许多个文档同时被打开。下面的表格列出了Windows应用程序的各种类型:

<table cellSpacing=1 cellPadding=7 width=550 align=center border=1> <tr> <td vAlign=top width=50% colSpan=2>

单文档界面(SDI)应用程序

</td> <td vAlign=top width=50% colSpan=2>

单文档界面(MDI)应用程序

</td> </tr> <tr> <td vAlign=top width=25%>

</td> <td vAlign=top width=25%>

</td> <td vAlign=top width=25%>

</td> <td vAlign=top width=25%>

</td> </tr> <tr> <td vAlign=top width=25%>

</td> <td vAlign=top width=25%>

</td> <td vAlign=top width=25%>

</td> <td vAlign=top width=25%>

</td> </tr> </table>

使一个给定的应用程序于上面的应用程序类型关联起来是不困难的。你可以简单地重复装载应用程序,并且注意是否每次有新的实例被创建。
使用JavaScript中的OLE Automation

5. 怎样处理应用程序的实例

比如,我们装载微软的Word三次,微软的Excel装载四次,Allaire HomeSite装载一次,Adobe Photoshop装载一次,然后看看结果的任务条,如图1所示。



(图1)

如图1所示,你可以看到Word和Excel都支持多个实例,而HomeSite和Photoshop不支持。这个任务条知识反应可视应用程序的实例。如果应用程序只是通过OLE Automation被装载,那它就不会出现在任务条上除非它是可见的。因此,你应该使用Ctrl+Alt+Del组合键来装载Close程序对话框(它可以让你彻底关闭应用程序)。

现在我们可能已经熟悉了实例,下面让我们来看看ActiveXObject() 和GetObject() 函数:

var objVar = new ActiveXObject(class);

如果对象被作为单一实例对象进行注册,那么对象就只有一个实例被创建。不管ActiveXObject()被多少次调用,你将得到对象的相同实例的引用。

如果对象示以多个实例对象(比如微软的Word)进行注册,那么对象的新实例被创建。而ActiveXObject()被调用的次数反应了实例的总数。比如 ,如果类为Word.Application,那么应用程序的新实例将被创建。

var objVar = new ActiveXObject(class, servername);

这条语句跟前面的语句是一样的,但是它在不同的服务器注册了ActiveX对象:

var objVar = GetObject(, class);

在Jscript中,这条语句将产生一个错误,因为Jscript不接受一个省略的参数紧跟着 一个逗号(,)。但是,这条语句的目的示想在Jscript中实现指定一个空的字符串而不是只是为了省略参数。在VB和VBScript中,这条语句将返回对象的实例。只有当对象不能发现的时候才会发生错误:

var objVar = GetObject(, class);

在Jscript中,这条语句将返回对象的当前实例。只有当对象不能发现的时候才会发生错误。
使用JavaScript中的OLE Automation

5. 怎样处理应用程序的实例

在VB和VBScript中,这条语句返回对象的新实例,除非对象被作为单一实例进行注册,如果是这种情况的话当前的实例将被返回。实际上,GetObject()函数的版本就是ActiveXObject()构造器。

var objVar = GetObject(pathname);

如果文档对象没运行,对象的服务器应用程序的新实例就被装载,并且应用程序被通知打开相应的文件。这里值得注意,参数必须代表现有的文件:

var objVar = GetObject(pathname, class);

即使文档已经被打开处于运行应用程序实例的状态下,应用程序新的实例总是被装载。

至此我们已经对ActiveXObject()和GetObject()的各种可能语法进行了讨论。最后让我们看看下面的总结表格:

<table cellSpacing=1 cellPadding=7 width=550 align=center border=1> <tr> <td vAlign=top width=50%>

</td> <td vAlign=top width=50%>

</td> </tr> <tr> <td vAlign=top width=50%>

</td> <td vAlign=top width=50%>

</td> </tr> <tr> <td vAlign=top width=50%>

</td> <td vAlign=top width=50%>

</td> </tr> <tr> <td vAlign=top width=50%>

</td> <td vAlign=top width=50%>

</td> </tr> <tr> <td vAlign=top width=50%>

</td> <td vAlign=top width=50%>

</td> </tr> <tr> <td vAlign=top width=50%>

</td> <td vAlign=top width=50%>

</td> </tr> <tr> <td vAlign=top width=50%>

</td> <td vAlign=top width=50%>

</td> </tr> </table>

6. 怎样提高脚本程序的性能

自从我们处理重的对象模型(比如Word.Application)和应用程序实例,注意系统的资源示相当重要的。一旦我们完成对应用程序实例的处理,我们必须去掉它,以从内存重清除对象的实例。在Jscript中有唯一的方法来实现,它就是应用程序对象的Quit()方法,以下是一个例子:

var wdApp = new ActiveXObject("Word.Application");

wdApp.Quit(); // tidy up

在Visual Basic中,不象Jscript和VBScript,设置对象变量为空是不能清除内存的。而且,如果没有其它对这个对象进行引用的话,这样的赋值操作将导致应用程序的关闭。不幸的是,在JSCript中我们必须使用Quit()方法在我们已经使用对象的时候来将它从内存中清除。而设置变量为零长度的字符串或者为空只是一个好的练习,它并不能起到清除内存的作用。

在教程中放置点至少代码了一个过程调用不得不在背景中被执行。最好得解决方法就是局部化高速缓冲对象引用。总得说来,这个技巧可以应用到对象以及Automation对象。下面看看脚本片段:

var exApp = new ActiveXObject("Excel.Application");

exApp.Workbooks(1).Worksheets(1).Cells(1, 1).Value = "First Cell";

exApp.Workbooks(1).Worksheets(1).Cells(1, 2).Value = "Second Cell";

exApp.Workbooks(1).Worksheets(1).Cells(1, 3).Value = "Third Cell";

exApp.Workbooks(1).Worksheets(1).Cells(1, 4).Value = "Fourth Cell";

exApp.Workbooks(1).Worksheets(1).Cells(1, 5).Value = "Fifth Cell";

下面的代码说明了以更有效的方法来实现:

var exApp = new ActiveXObject("Excel.Application");

var exWbook = exApp.Workbooks(1).Worksheets(1);

exWbook.Cells(1, 1).Value = "First Cell";

exWbook.Cells(1, 2).Value = "Second Cell";

exWbook.Cells(1, 3).Value = "Third Cell";

exWbook.Cells(1, 4).Value = "Fourth Cell";

exWbook.Cells(1, 5).Value = "Fifth Cell";

7. 怎样处理集对象

Automation对象与其它的Jscript对象有些有相同的结构。它暴露了多种方法和属性,我们可以对它们进行处理。如果你从来没有接触Visual Basic,你可能就不熟悉集对象了。集就是相关项的组。集用在Visual Basic主要是为了保持跟踪许多事情,比如从你的程序(表单集)中装载表单,或者表单(控件集)中的所有控件。

Visual Basci提供了集类,这样你就可以创建你自己的集了。在集对象中的每一项被定义为一个Variant,即Visual Basic中的一种16字节的数据类型。OLE Automation集即使一些通过标准OLE界面暴露出来的集。一个集对象包含四个标准的元素:

(1)colObj.Add(item[, key][, before]);

Add()方法为集增加项。除了数据本省,你还可以利用从集中的得到的成员来指定一个关键数值。这里注意,最后一个参数不能通过Jscript来指定。

(2)colObj.Count

Count属性返回了在集中项的数目。

(3)colObj.Item(index)

Item()方法利用所以从集中取回项。

(4)colObj.Remove(index);

这个Remove()方法是通过所以来从集中删除项。

集跟数组很相似,但是有下面的理由反应集是更好的选择:

从数组中间删除一项是很笨拙的。而Remove()方法使得用户可以很容易地删除集中的任何项,这是根据它在集中的位置或者项的键。

你不必重新定义一个集对象,而在Visual Basic中要经常改变动态数组的长度。所以这会使得结果更清除,代码具有较好的可维持性。

(3)利用键,集对象有非常快速检索能力,而数组就不行了。即使你不知道项在集中的位置,你都可以键容易地找到它。

既然我们处理Automation 对象,所以熟悉集是很重要的。在的脚本中即会发现你正在处理它们,而且,你还会注意到Item()方法的重要性,如下所示:

colWorkOrders.Item("W050580").Priority = 4;

JavaScript处理集的主要问题是它没有任何的函数可以循环浏览集中的每一项。而在Visual Basic(或者VBScript)可以利用For Each..Next结构,但是利用Jscript是不可能的。这个问题是你在编写脚本的时候所应该解决的



↑返回目录
前一篇: 用JavaScript实现利用FLASH嵌入声音
后一篇: JavaScript 使用HoTMetal