COM(Component Object Model,组件对象模型)是Windows下广泛使用的模型,允许不同的软件部分交互。由于已经封装,所以这些交互在不需要知道该软件模块具体实现方法的情况下完成,它已经变为程序交互使用的重要手段。这项技术始于1993年,并于1997年前后逐渐流行。COM对象流行的原因在于可以很方便地用在在自动化接口及扩展。有些程序,如Microsoft Office用其为脚本作者向外提供对象模型;另外一些程序,如Internet Explorer和Windows Media Player用其向外提供了用户界面。这样即可嵌入到其他的程序中,甚至是网页中。COM能够扩展为DCOM系统,这样即可提供分布式通信,并允许将对象向远程主机发布。DCOM可以不必知道对象是否运行在同一主机上即可很方便地创建分布式系统, WMI机制即使用DCOM作为与远程主机的通信媒介。
伴随.NET框架的优点,微软推出了其他对象交互的方法。.NET 框架指定了一个公用的类型系统,允许不同开发语言开发的软件部件相互间可以如由同种语言写成一样方便地交互。.NET的远程机制提供了分布式通信的方法,甚至支持远比COM本身更多复杂的操作。随着.NET框架3.0的发布,在进程间和主机间通信方面用户又多了另外的选择,即Windows Communications Foundation。传统的COM组件已经被扩展为复杂的系统,软件开发人员已经很难处理相关错综复杂的交互。基于.NET的组件技术已经显现了其优势,并逐渐开始替换COM的地位,并有人已经宣称COM已死。事实上并非如此,微软会在当前直至将来的操作系统中支持COM,很多依靠COM实现自动化和交互界面是方便易用的;另外在脚本环境中使用COM对象很简单,PowerShell提供了完美的支持。在向外提供 COM对象功能时,用户不需要处理任何复杂的转换,并且可以使用PowerShell调用COM对象。
本文将针对Microsoft Office工具,如Word、Excel,以及Internet Explorer浏览器的自动化编程。并且示范如何重用由VBScript和Jscript语言写成的代码,这些代码基于Windows Scripting Host技术,最终可以归结为COM组件的调用。
1 COM如何工作
有关COM的所有操作围绕对象界面开展,而组件平台本质上是对象为向导的。它将界面定义为契约,即一系列方法和属性的集合。对象由这些方法和属性实现,使用契约使得其他对象在知道支持何种操作的前提下使用该对象的接口成为可能。COM界面是对象向外开放的一系列方法和属性通过统一标识符(GUID)来区分和标识不同的COM对象,执行界面的类也通过GUID唯一标识。GUID可以被称之为“classID”,或者“CLSID”。这些类保存在Windows注册表中,是系统在创建对象时使用的。GUID是一长串字符和数字的组合,很难记忆。如Internet Explorer Application对象的GUID类似于{D30C1661-CDAF-11D0-8A3E-00C04FC9E26E}。COM的创建者提出了一种更好的标识方法,即Program ID字符串,也称为“ProgID”。它比CLSID更为友好,如CLSID对应的ProgID即InternetExplorer.Application。根据前面的介绍ProgID和CLSID的对应关系也应该由注册表中对应的键值控制的。
程序要调用一个COM对象时,需要向Windows提供将要调用对象的CLSID或者ProgID。Windows将会通过注册表中的信息查找和定位对象,然后创建对象并根据创建对象时传递的参数确定是否需要立即显示界面。如果需要,则会返回一个指向界面的对象引用,用户可以如同正常对象那样调用这个对象引用。这种对象的创建机制完全与开发语言、进程及技术无关。COM自己会知道如何创建代理对象,可以自动汇集前台、后台的参数和结果。这样用户即可不用关心对象是在进程,还是在网络中的主机上运行。
2 PowerShell如何支持COM
PowerShell构建与.NET Framework之上,而框架已经提供了对COM的近乎完美的支持。如可以用.NET的机制获取封装COM对象的.NET的类型,用Activator类创建这个类的实例。图1所示为测试创建的Internet Explorer实例。
在前述的例子中需要强调:一是从GetTypeFromProgID()方法取回的类型的别名称之为“-ComObject”,所有的COM对象都是被封装为这个类型;二是在实例中创建真实对象通过传递这个类型给Activator类的CreateInstance()方法来实现。这就是经任何.NET类实例化的通用方法,如Name属性的值取回的对象是一个Internet Explorer浏览器的实例。
上例用两行代码完成了创建对象的操作, Activator对象用来创建.NET对象。New-Object cmdlet可以通过ProgID创建COM对象,但是它需要被显式告知正在创建的是一个COM对象。为了说明这一点,可以将ProgID传递给ComObject作为参数值,如图2所示。
图1 为测试创建的Internet Explorer的COM对象实例
图2 将ProgID传递给ComObject作为参数值
在上例能够看到这是一个创建COM对象更便捷的方法,这样创建对象的代码会更加简单且可读性强。PowerShell的类型系统提供了关于COM对象内置的适配器,它知道如何查询COM类型库信息,并将对象封装为与.NET对象完全类似的对象类型。
不支持的特性:别名、运行对象和事件
创建和访问对象并不是COM的所有功能,COM对象能够通过文件名或路径唯一标识。类似URL,称之为“别名”(moniker)。用户可以通过别名来唯一地定位和调用,如获取Excel的Worksheet的引用或者指向Word的Document的第2段。COM另外一个有用的特性是运行中的对象清单,用于保存已注册对象,如在启动Word时Microsoft Word Application实例获取在这个清单中注册的对象属性。COM和.NET对象类似,能让客户端接受事件,会在条件被触发时捕获它们。
所有这些属性在PowerShell中不可用,因为这些属性基本上很少用到。
作者: 付海军
版权:本文版权归作者所有
转载:欢迎转载,为了保存作者的创作热情,请按要求【转载】,谢谢
要求:未经作者同意,必须保留此段声明;必须在文章中给出原文连接;否则必究法律责任
个人网站: http://txj.shell.tor.hu/