Chinaopub.coM 下载 第16章ASP脚本组件 在研究ASP时,一个首要问题是如何编写能够为ASP页面提供运行期文本的组件。三年以 来,我们使用了很多方法去解决这个问题,使用设计期 ActiveX控件( Design-time Active x Control,DTC)和ASP组件是解决这一问题的两种不同方法。 不要将DTC与分布事件协同( Distributed transaction coordinator)相混淆 首先,DTC是可视化的,在调用ASP页面之前,它关联于用于生成ASP页面运行期文本的 创作工具。可以将其理解为类似于先进的Word和Exce宏。一旦它们完成运行并你保存了页面 ASP脚本仅包含代替控件的文本。不必担心可能造成的额外的下载,因为程序已经使用了 DTC,而DTC是开发期控件,因此运行时不进行任何多余的下载。通常,不必为自己的项目 编写DTC,而是使用开发工具提供的DTC。例如 Visual inter dev就提供大量DTC供使用 正如在前面章节看到的,ASP组件更为直接和特定,并且只在运行期内发生作用。它们 能够添加基于运行期环境的代码。这些组件用C++或Ⅴ isual basic编写,并由IS控制在服务器 上加载和执行。在使用ASP时,将直接影响站点的整体性能。 本章将介绍用脚本语言编写的ASP组件。这种ASP组件是名为 Windows脚本组件( Windows Script Component,wsC的常用技术的一个特例。它使程序员能够仅仅使用一种脚本语言如 VBScript或 JScript编写几种类型的COM对象。如果正在使用 Windows2000或IE50,那么计 算机上已经安装了这些组件。但是,也可以在 Windows nt环境下的IS40中或 Windows9x环 境下的PWS中运行。 所以,这里将简单介绍WSC技术的主要特征,主要内容有: ·使用脚本语言编写COM对象的技术基础。 ·怎样使用脚本语言编写COM对象 怎样编写ASP脚本组件。 ASP脚本组件同其他ASP组件的区别。 在讲述理论之后,举个例子:用一种有力而易于维护的方法封装HTML的表以格式化数 据 16.1使用WSC的环境 如果要重现在这章中所要讲述的所有内容,你的系统需要安装相应的一些程序。首先 把浏览器指向微软脚本网站:htt:/msdn.microsof.com/scripting并下载wSC包,这是一个自 安装文件,包含以下内容: WSC的二进制驱动程序。 ·文档。 帮助编写组件的向导。 如果你已经安装了 Windows2000或IE5.0,则系统已经具有其驱动程序。安装 Windows
下载 第16章 ASP脚本组件 在研究A S P时,一个首要问题是如何编写能够为 A S P页面提供运行期文本的组件。三年以 来,我们使用了很多方法去解决这个问题,使用设计期 A c t i v e X控件(Design-time ActiveX C o n t r o l,D T C )和A S P组件是解决这一问题的两种不同方法。 不要将D T C与分布事件协同(Distributed Transaction Coordinator)相混淆。 首先,D T C是可视化的,在调用A S P页面之前,它关联于用于生成 A S P页面运行期文本的 创作工具。可以将其理解为类似于先进的Wo r d和E x c e l宏。一旦它们完成运行并你保存了页面, A S P脚本仅包含代替控件的文本。不必担心可能造成的额外的下载,因为程序已经使用了 D T C,而D T C是开发期控件,因此运行时不进行任何多余的下载。通常,不必为自己的项目 编写D T C,而是使用开发工具提供的 D T C。例如Visual InterDev就提供大量D T C供使用。 正如在前面章节看到的, A S P组件更为直接和特定,并且只在运行期内发生作用。它们 能够添加基于运行期环境的代码。这些组件用 C + +或Visual Basic编写,并由I I S控制在服务器 上加载和执行。在使用A S P时,将直接影响站点的整体性能。 本章将介绍用脚本语言编写的 A S P组件。这种A S P组件是名为Wi n d o w s脚本组件( Wi n d o w s Script Component,W S C )的常用技术的一个特例。它使程序员能够仅仅使用一种脚本语言如 V B S c r i p t或J S c r i p t编写几种类型的C O M对象。如果正在使用 Windows 2000 或IE 5.0,那么计 算机上已经安装了这些组件。但是,也可以在 Windows NT环境下的IIS 4.0中或Windows 9x环 境下的P W S中运行。 所以,这里将简单介绍W S C技术的主要特征,主要内容有: • 使用脚本语言编写C O M对象的技术基础。 • 怎样使用脚本语言编写C O M对象。 • 怎样编写A S P脚本组件。 • ASP脚本组件同其他A S P组件的区别。 在讲述理论之后,举个例子:用一种有力而易于维护的方法封装 H T M L的表以格式化数 据。 16.1 使用W S C的环境 如果要重现在这章中所要讲述的所有内容,你的系统需要安装相应的一些程序。首先, 把浏览器指向微软脚本网站: h t t p : / / m s d n . m i c r o s o f t . c o m / s c r i p t i n g并下载W S C包,这是一个自 安装文件,包含以下内容: • WSC的二进制驱动程序。 • 文档。 • 帮助编写组件的向导。 如果你已经安装了 Windows 2000或IE 5.0,则系统已经具有其驱动程序。安装 Wi n d o w s
498Ap高程 下载 98或IE401的系统也是这样的,但其提供的是语法上稍有不同的较老版本。只要从微软的网 站下载其软件包则一切可迎刃而解 wSC向导并不包含在任何版本的浏览器和操作系统中,需要从微软站点下载。 16.2一个 Windows脚本组件 下面从 Windows脚本组件的定义开始 个 Windows脚本组件就是一个使用脚本语言编写的cOM对象。 初看这个定义会感觉到很奇怪:真的可以用脚本语言编写COM对象吗?下面的这些情况 也说明了这种疑惑的合理性 COM对象是二进制的文件,而Ⅴ SCript和 JScript不生成二进制文件。 COM对象具有一个众所周知的二进制布局,脚本语言如何实现这种布局? COM对象提供接口,如何使脚本语言也能这样做。 COM对象需要注册和一个 CLSID,脚本语言如何处理这些问题。 上面的这些疑问将在下面给出相应的详尽解答 16.2.1发展历史 最初,组件化Web的尝试是由1997年发布的IE4实现的。到目前为止,IE仍是唯一的支持 动态超文本标记语言( DHTML)Scriptlet的浏览器(它是今天web组件的原形)。 DHTMLScriptlet 主要指嵌入另一HTML的HTML。通过使用一个特定的命名约定,子页面可以向容器页面提供 个可编程的接口,并允许容器页面调用其方法、属性或激活事件 使用 DHTML Scriptlet同使用 Activex控件并没有什么不同,但是作为组件,二者主要分 别用于I和 Visual basic。从效率上来讲,它们并不是真正的由脚本语言编写的可重复使用组 件。此外, DHTML Scriptlet组件是为显示用户界面而设计的,而不是作为被请求页面的辅助 函数 从 DHTML Scriptlet发展到 Scriptlet 不久便产生了简单地称为 Scriptlet的组件。它们便是今天WSC的祖先。 Scriptlet是一种常 规的COM对象,可以从任何感知COM的开发工具调用,如 Delphi、 Power Builder、MFC和 DHTML Scriptlet同 Scriptlet相比较,其本身并没有什么不同,而编写方式却大不相同。 组件源代码的结构由HTML和脚本代码的混合体变为XML COM对象并不仅是代码。它提供标准的二进制布局。这意味着当编写COM对象时,至少 需要考虑两方面信息,分别是实现的接口和注册数据。正如我们前面注意到的那样,使用脚 本语言无法传递这种特殊的信息。 微软有两种选择,分别是: ·重新选择一个特殊的命名约定以插入注册和接口信息。 使用完全不同的语法编写组件。 微软选择了后者并使用XML定义组件的语法
9 8或IE 4.01的系统也是这样的,但其提供的是语法上稍有不同的较老版本。只要从微软的网 站下载其软件包则一切可迎刃而解。 W S C向导并不包含在任何版本的浏览器和操作系统中,需要从微软站点下载。 16.2 一个Wi n d o w s脚本组件 下面从Wi n d o w s脚本组件的定义开始: 一个Wi n d o w s脚本组件就是一个使用脚本语言编写的 C O M对象。 初看这个定义会感觉到很奇怪:真的可以用脚本语言编写 C O M对象吗?下面的这些情况 也说明了这种疑惑的合理性: • COM对象是二进制的文件,而V B S c r i p t和J S c r p t不生成二进制文件。 • COM对象具有一个众所周知的二进制布局,脚本语言如何实现这种布局? • COM对象提供接口,如何使脚本语言也能这样做。 • COM对象需要注册和一个C L S I D,脚本语言如何处理这些问题。 上面的这些疑问将在下面给出相应的详尽解答。 16.2.1 发展历史 最初,组件化We b的尝试是由1 9 9 7年发布的I E 4实现的。到目前为止, I E仍是唯一的支持 动态超文本标记语言( D H T M L ) S c r i p t l e t的浏览器(它是今天We b组件的原形)。D H T M L S c r i p t l e t 主要指嵌入另一H T M L的H T M L。通过使用一个特定的命名约定,子页面可以向容器页面提供 一个可编程的接口,并允许容器页面调用其方法、属性或激活事件。 使用DHTML Scriptlet同使用A c t i v e X控件并没有什么不同,但是作为组件,二者主要分 别用于I E和Visual Basic。从效率上来讲,它们并不是真正的由脚本语言编写的可重复使用组 件。此外,DHTML Scriptlet组件是为显示用户界面而设计的,而不是作为被请求页面的辅助 函数。 从DHTML Scriptlet发展到S c r i p t l e t 不久便产生了简单地称为 S c r i p t l e t的组件。它们便是今天 W S C的祖先。S c r i p t l e t是一种常 规的C O M对象,可以从任何感知 C O M的开发工具调用,如 D e l p h i、P o w e r B u i l d e r、M F C和 Visual Basic。 DHTML Scriptlet同S c r i p t l e t相比较,其本身并没有什么不同,而编写方式却大不相同。 组件源代码的结构由H T M L和脚本代码的混合体变为X M L。 C O M对象并不仅是代码。它提供标准的二进制布局。这意味着当编写 C O M对象时,至少 需要考虑两方面信息,分别是实现的接口和注册数据。正如我们前面注意到的那样,使用脚 本语言无法传递这种特殊的信息。 微软有两种选择,分别是: • 重新选择一个特殊的命名约定以插入注册和接口信息。 或: • 使用完全不同的语法编写组件。 微软选择了后者并使用X M L定义组件的语法。 498计计ASP 3 高级编程 下载
Chinapub.coM 第6章4本组件499 下载 IE40 I Scriptlet同目前的wsC的不同点在于:后者使用XML模式存储对象的附加信息 16.2.2 HelloWorld WSC WSC文件是扩展名为wsc的XML文件,以前是 正如其他的 Hello world例子一样, wSC版的例子也是很简单 <registration progid="Helloworld. Component"/> <method name='Welcome"/ MsgBox Hello, world* End Function </component> 脚本组件中所有的信息都必须置入< component>、</ component>标记对中。也可以使用 < registration>、< public>和< script>标记。它们分别用 CLSID或 ProgID、实现的接口及其实际 功能来描述COM对象。 现在你应当对WSC文件有了一个初步的了解,下面将更为详尽地讲述如何构造WSC 16.3WsC的结构 首先,WSC的整个结构可以分解为如下三层: ·描述层:提供组件的元数据信息。 脚本层:包含所需的脚本函数 运行期层:以二进制提供给客户一个熟悉的COM布局 图16-1显示了WSC源代码文件的不同层。 描述层,定义对象的名称及 <method name="Welcome"/> 其提供的方法等 /public> MsgBox"Hello, World 脚本层,包括组件工作所需 的代码 ≤ component> 运行期层,包括解释脚本代 WSC解释器 码和向客户端提供相关的 COM布局的DLL 图16-1wSC的源代码结构
IE 4.01 Scriptlet同目前的W S C的不同点在于:后者使用X M L模式存储对象的附加信息。 16.2.2 HelloWorld WSC W S C文件是扩展名为 . w s c的X M L文件,以前是 . s c t。正如其他的 H e l l o Wo r l d例子一样, W S C版的例子也是很简单: 脚本组件中所有的信息都必须置入 < c o m p o n e n t >、< / c o m p o n e n t >标记对中。也可以使用 < r e g i s t r a t i o n >、< p u b l i c >和< s c r i p t >标记。它们分别用 C L S I D或P r o g I D、实现的接口及其实际 功能来描述C O M对象。 现在你应当对W S C文件有了一个初步的了解,下面将更为详尽地讲述如何构造 W S C。 16.3 WSC的结构 首先,W S C的整个结构可以分解为如下三层: • 描述层:提供组件的元数据信息。 • 脚本层:包含所需的脚本函数。 • 运行期层:以二进制提供给客户一个熟悉的 C O M布局。 图1 6 - 1显示了W S C源代码文件的不同层。 图16-1 WSC的源代码结构 第1 6章 A S P脚本组件计计499 下载 描述层,定义对象的名称及 其提供的方法等 脚本层,包括组件工作所需 的代码 运行期层,包括解释脚本代 码和向客户端提供相关的 COM布局的DLL WSC解释器
500A5p3高装程 Chinapub.com 下载 16.31描述层 在这一层中共有四种基本的标记可供使用,它们是: <registration> <public> 酸入 Registration>标记包含了向 Windows注册表中添加组件时需要使用的信息。在这里,可以 件进行较少的描述,如 Progld和 ClassID,也可以是任何基于注册或取消注册的可执行代 举个例子,一个新创建的组件会有一个类似下面的注册标记: <registration description"The first Helloworld WSC <I--optional--> version=1.00. progid="Helloworld. c1 assad={6432490f-0d48-48e3-bbe7-e2e773fc843e} description和 version属性是可选的,但是必须至少指定一个 progid和 classid属性。否则, 当试图注册组件时将产生错误 当为单一类型的WSC创建COM对象时,必须有一个 CLSID。没有 CLSID的WSC无法工作, 所以在注册过程中自动生成 CLSID。如果不指定 CLSID,特定的注册COM对象的系统程序 ( regsvr32exe)会为它创建一个。但是要记住,只有最新的用于IE5.0、 Windows2000和wSC 包的 regsvr32.exe才会这样做。否则,注册过程将崩溃。 Progid用于在如Ⅴ SCript的 CreateObject或 JScript的 ActiveXObject这样的后绑定函数中创 建对象实例。实际上,在脚本开发环境中,一个没有 ProgId的组件几乎没有任何作用。不定 义 ProgId,将无法用 CreateObject或 ActiveXObject来创建对象实例。只有 Windows Script Host 2.0才允许仅使用 CLSID来创建对象实例 在注册和取消注册时执行代码 如果需要,组件具有在注册或取消注册时运行预定义代码的功能。通常,从 regsvr32.exe 的视角来看,COM对象的注册是从COM对象DLL中调用一个函数。但是,每个WSC都通过服 务器模块( scrobj. dll)注册。一旦调用,它就知道了正在工作的wSC文件的名称,并且创建 COM对象的所有注册项。 这个DLL还在< registration>标记中查找两个函数中的一个。根据组件是在注册还是在取 消注册,它们分别是 Register和 Unregister <registration description="This is my component <!--。 ption1--> version <!-- optional-: progid=· MyComp.wsC classid="{e8c35060-1879-11d3-b17c-00c0dfe39736}> <script language:VBScript> Function Registe MsgBox Registering- (e. g. generate a type-library on-the-fly)
16.3.1 描述层 在这一层中共有四种基本的标记可供使用,它们是: • <registration> • <public> • <implements> • <resource> 1. <registration> < r e g i s t r a t i o n >标记包含了向Wi n d o w s注册表中添加组件时需要使用的信息。在这里,可以 对组件进行较少的描述,如 P r o g I D和C l a s s I D,也可以是任何基于注册或取消注册的可执行代 码。 举个例子,一个新创建的组件会有一个类似下面的注册标记: d e s c r i p t i o n和v e r s i o n属性是可选的,但是必须至少指定一个 p r o g i d和c l a s s i d属性。否则, 当试图注册组件时将产生错误。 当为单一类型的W S C创建C O M对象时,必须有一个C L S I D。没有C L S I D的W S C无法工作, 所以在注册过程中自动生成 C L S I D。如果不指定 C L S I D,特定的注册 C O M对象的系统程序 ( r e g s v r 3 2 . e x e )会为它创建一个。但是要记住,只有最新的用于 IE 5.0、Windows 2000和W S C 包的r e g s v r 3 2 . e x e才会这样做。否则,注册过程将崩溃。 P r o g i d用于在如V B S c r i p t的C r e a t e O b j e c t或J S c r i p t的A c t i v e X O b j e c t这样的后绑定函数中创 建对象实例。实际上,在脚本开发环境中,一个没有 P r o g I D的组件几乎没有任何作用。不定 义P r o g I D,将无法用C r e a t e O b j e c t或A c t i v e X O b j e c t来创建对象实例。只有Windows Script Host 2 . 0才允许仅使用C L S I D来创建对象实例。 在注册和取消注册时执行代码 如果需要,组件具有在注册或取消注册时运行预定义代码的功能。通常,从 r e g s v r 3 2 . e x e 的视角来看,C O M对象的注册是从C O M对象D L L中调用一个函数。但是,每个 W S C都通过服 务器模块 ( s c r o b j . d l l )注册。一旦调用,它就知道了正在工作的 W S C文件的名称,并且创建 C O M对象的所有注册项。 这个D L L还在< r e g i s t r a t i o n >标记中查找两个函数中的一个。根据组件是在注册还是在取 消注册,它们分别是R e g i s t e r ( )和U n r e g i s t e r ( ): 500计计ASP 3 高级编程 下载
第16章9件501 下载 End function Function Unregister MsgBox "Unregistering. End function </script </registration> 定义这些函数取决于是否需要。在注册组件前没有必要声明其中任何一个。当然,可以 使用这两个函数去做更多的事情,而不仅仅是显示一个对话框。举个例子,可以动态生成组 件类型库 2. <public> public>标记定义了组件的公共编程接口。换句话说,定义了组件提供的并且在客户端可 以调用的方法、属性和事件。其语法相当直接明了: <publi proper ty name=My Property> <put/> ≤/ property> <parameter name="param1"/> cevent name="OnEvent'> <parameter name=param1/> /event> </public> 其中,name属性定义了每个条目的公共名称。在上面的代码中,属性是通过变量 My Property进行描述的,而方法体全部在一个名为 My Method的函数中。二者都定义在wSC的 < script>标记中。下面是更多的关于这方面的内容。 (1)内部名称 对于方法和属性同样也可以使用一个内部名称。这通过 internalname属性来赋值。内部名 称的基本用途是在WSC文件中引用方法或属性 <public> <property name="My Property' internalname="mMyProperty'> <method name=' MyMethod" internalname= "DoMy Method"> <parameter name="param1/> </public> 在这种情况下, My Property的属性通过变量对 m My Property来实现。同时,当客户调用 MyMethod方法时,实际调用的是 DoMy Methodr函数 (2)指定参数 个方法根据需要可以有任意多个参数。这里,name属性指示了形参名称。同样,事件 也可以有任意个参数,尽管一些老的文件没有提到这一点 (3)只读和只写属性
定义这些函数取决于是否需要。在注册组件前没有必要声明其中任何一个。当然,可以 使用这两个函数去做更多的事情,而不仅仅是显示一个对话框。举个例子,可以动态生成组 件类型库。 2. <public> < p u b l i c >标记定义了组件的公共编程接口。换句话说,定义了组件提供的并且在客户端可 以调用的方法、属性和事件。其语法相当直接明了: 其中, n a m e属性定义了每个条目的公共名称。在上面的代码中,属性是通过变量 M y P r o p e r t y进行描述的,而方法体全部在一个名为 M y M e t h o d的函数中。二者都定义在 W S C的 < s c r i p t >标记中。下面是更多的关于这方面的内容。 (1) 内部名称 对于方法和属性同样也可以使用一个内部名称。这通过 i n t e r n a l n a m e属性来赋值。内部名 称的基本用途是在W S C文件中引用方法或属性。 在这种情况下,M y P r o p e r t y的属性通过变量对 m _ M y P r o p e r t y来实现。同时,当客户调用 M y M e t h o d方法时,实际调用的是D o M y M e t h o d函数。 (2) 指定参数 一个方法根据需要可以有任意多个参数。这里, n a m e属性指示了形参名称。同样,事件 也可以有任意个参数,尽管一些老的文件没有提到这一点。 (3) 只读和只写属性 第1 6章 A S P脚本组件计计501 下载