摘 要:本文探讨在Microsoft® Windows® 2000和Windows 98第二版中并行共享组件的实现问题,同样在Windows认证规范方面进行了讨论。本文包括的内容涉及:新的并行组件的创建,以及使用DLL/COM重定向来处理同一组件的不同版本之间的不兼容问题。本文包括编写和安装并行组件,以及重新打包和测试应用程序的指导原则。
内容
简介 一点背景知识 新的组件共享策略 两种策略的比较 创建新的并行组件 编写并行组件的指导原则 安装并行组件 DLL/COM重定向 使用DLL/COM重定向
简介
现代的操作系统和应用程序是利用多个组件建立起来的。一个组件是一个自约束的软件实体,提供可以由各种应用程序广泛使用的一组功能。由于个别的组件是由多个应用程序使用的,因此组件共享至关重要。共用组件的成功共享要求任何共享的组件能够完全象该组件的以前版本那样运行。实际上,由于对使用该共享组件的所有配置进行测试的困难,100%的向后兼容是很困难的,甚至是不可能达到的。较新的应用程序将不再使用较旧的应用程序使用的同一个组件,并且随着时间的推移,修正和改进这个组件变得日益困难。 另外,组件的实际功能是不容易确定的。应用程序可能会依赖于事先没有预计到的某些没有被列为组件核心功能的部分。例如,一个应用程序可能会依赖于组件中的一个缺陷,从而当组件的开发人员将这个缺陷修正时,应用程序将无法正常工作。这就是平常所说的“DLL陷阱”。使用组件的大量应用程序使这个问题变得尤其令人头疼。 组件缺乏向后兼容性的问题会导致在部署一个新的应用程序时,将不得不破坏已经部署的应用程序或减少新应用程序的功能。任何新的应用程序都需要一个与已经部署的版本不同的新版本的共享组件。为了在增强应用程序稳定性的同时提供成功的组件共享,微软公司已经在Windows 2000 和Windows 98第二版中引入了并行共享,这样就可以通过选择性隔离来实现组件共享。
一点背景知识
在我们深入讨论并行共享之前,让我们首先了解一些问题背景以及“DLL陷阱”引发的问题。
组件共享
Windows从它诞生的那一天起就一直在采用共享的概念。所有的操作系统都在提供一套健壮、完备的服务的需要和有限的硬件资源之间进行权衡。一直到最近,CPU和磁盘空间还是PC平台上十分珍贵的资源。在有限的空间里安装操作系统和应用程序的一个显而易见的解决方法是尽可能地使用共享代码。 除了其它大量好处之外,代码共享还可以最大限度地利用硬件资源和最小化为保证代码质量而需要进行的测试工作。代码共享是使Windows获得成功的一个重要原因。 Windows并不仅仅局限于共享代码。应用程序和组件的状态在操作系统的很多地方都可以找到:可以通过注册表、针对某个应用程序的文件系统中的数据文件、以及可以获取全局变量的Windows API中获得应用程序和组件的当前状态。这种共享方式为多个软件开发商创建的应用程序提供了高度的互用性,从而可以减少软件开发成本和使软件更有效率。 但是,共享需要付出一定的代价。共享意味着应用程序之间彼此互相依赖,这将可能使应用程序变得很脆弱。对一个组件的改动可能会对其它组件产生不可预计的后果。典型地,某个应用程序可能依赖于某个共享组件的特定版本。而另一个应用程序可能和同一共享组件的更新版本(或以前的老版本)一起安装,这样,第一个应用程序就会由于共享组件版本的变化而受到损害。在极端情况下,以前一直正常工作的应用程序将会神秘地开始出现各种奇怪现象,甚至不能正常工作。这种情况常常被称为“DLL陷阱”。
隔离
和共享相反的做法是隔离。可以通过将所有应用程序使用的资源和代码静态地捆绑到应用程序来将应用程序进行隔离。但是,对那些依赖于COM或任何其它全局存储的系统资源的应用程序而言,完全隔离是不可行的。 减少应用程序的脆弱性的一个解决方案是选择性地隔离应用程序和组件。在这种情况下,可能所有应用程序都可以访问一个相同的组件,但是这个组件的多个版本此时可以并存了。组件开发商可以自由地创建旧组件的新版本:或者改进、或者修正缺陷。而另一方面,顾客可以从多个版本的组件中选择适合某个应用程序的特定版本。这就象到一个汽车配件商店为你在1984年购买的Chevy汽车挑选一个燃料泵一样。你在货架上各种规格和型号的泵中找到你需要的泵。对组件而言,关键的问题是为每个应用程序提供合适的版本,并将各个版本之间隔离开。更进一步说,通过重定向,应用程序可以配置为仅使用适合这个特定应用程序的特定组件版本,而不管当前部署有那些其它的组件版本或将来会加入哪些更新的版本。
并行共享
为了实现这种应用程序和组件的隔离,Microsoft Windows 2000 和 Windows 98第二版加入了一种新的组件共享特性,称为“并行共享”。并行共享通过有选择性的隔离来最大限度地避免“DLL缺陷”。它允许同一组件(COM或Win32®组件)的多个版本同时在不同的进程里运行。这样,即使另一个应用程序需要同一组件的另一个版本,某个应用程序也可以使用在设计和测试时它所使用的组件版本。这种并行共享的组件共享特性允许开发人员建立和部署更为可靠的应用程序,因为在这种情况下,开发人员可以在独立于系统上其它应用程序的情况下确定他们自己的应用程序将使用的组件版本。
新的组件共享策略
Windows 2000和Windows 98第二版中的并行共享策略有如下两种:
- 创建并行组件。 开发人员创建支持组件多个版本同时运行的新组件。这些新组件的顾客现在可以使用在创建和安装他们的应用程序时所使用的组件版本,而不管他们的计算机上安装有这个组件的其它什么版本。
- DLL/COM 重定向。 开发人员和管理人员将现存的应用程序和组件重新打包,以便让共享组件的特定版本被用于需要它们的应用程序,并让同一组件的各个版本并行运行。
不管是新创建的并行组件还是作为重新配置后的现存应用程序的一个部分,并行组件并不是在所有情况下都被支持的。
- 创建并行组件的主要场景是当组件的宿主应用程序是一个容器应用程序并且组件在这个应用程序的进程里运行时发生。例如,当控件被一个Windows桌面应用程序使用时(用Microsoft Visual Basic®或 Visual C++®编写的控件可以很好地用于并行设计。不推荐在服务器上使用并行组件)。
- 使用DLL/COM重定向的主要场景是当新的客户端应用程序正在被部署到已经支持其它应用程序的计算机上、或者对于由于安装其它应用程序而带来的共享组件的变化,新的应用程序需要更强的柔韧性时。不推荐在服务器上使用DLL/COM重定向。
注意DLL/COM重定向的目的是解决现存应用程序和组件在部署时带来的应用程序冲突问题。在开发一个新的应用程序或新的组件时,最好的策略是开发具有固有隔离性质的并行组件。
两种策略的比较
下表比较了DLL重定向和创建并行(SxS)组件这两种策略,并且给出了在不同场景下选择合适方法的指导原则。
表1. 并行策略比较
属性 |
并行组件 |
DLL/COM重定向 |
主要目的是什么? |
创建健壮的新组件,以便在将来对组件做使组件无法“向后兼容”的改动时,新组件的各个版本不再受制于这种改动。 |
将现存应用程序隔离起来,避免因为安装带不相容共享DLL的其它应用程序而带来的问题。 |
组件的不同版本和使用它们的应用程序之间是隔离的吗? |
是。部署并行组件的目的就是要将并行组件和使用它们的应用程序隔离开。 |
是。使用DLL/COM 的应用程序使用安装在应用程序目录下任何版本的共享组件,而不管在系统的其它地方还安装有组件的其它什么版本。 |
需要新的代码或者对现存代码进行改动吗? |
需要。创建并行组件(或使现存组件成为并行组件)至少需要COM的注册代码改变为允许通过相对路径访问。可能还需要其它一些代码上的改动来保证同时运行的不同并行组件的全局状态被正确地处理。 |
不需要。DLL/COM重定向允许应用程序在没有任何代码改动或重新编译的情况下进行配置,以安装和运行并行组件。这就允许无法访问应用程序源代码的管理人员对应用程序进行重新配置来解决DLL缺陷问题。 |
这种策略是否可以应用于所有场景? |
是。并行组件设计和编写的目的就是让它可以被安装和并行运行。因此,精心设计、开发和测试后的并行组件(以及使用它们的应用程序)将不再受和DLL陷阱有关的问题困扰。 |
不是。DLL/COM重定向并不需要改动代码。现存应用程序和组件在设计时可能并不要求同一组件的不同版本可以同时运行。经验表明,在大多数情况下,现存应用程序和组件都可以运行并行组件,但是对特定场景需要对这一点进行验证。(请参看选择隔离组件) |
一般的经验是:
- 如果DLL陷阱问题使得现存应用程序的部署无法进行,那么使用DLL/COM重定向来隔离冲突组件。(要进一步了解这个选项,请参看下面的场景描述)。
- 如果你正在建造一个新的应用程序并想在设计和开发中避开DLL陷阱问题,那么你应该开发并行组件。
创建新的并行组件
并行共享要求在创建新的应用程序时,开发人员应该创建并行组件。这些并行组件是通常的COM或Win32组件,唯一不同之处在于,这些并行组件被安装到应用程序所在的目录下(或应用程序的子目录下)而不是安装到系统目录中。它们被隔离到某个特定的应用程序,并且不可以在所有应用程序之间进行全局共享。 这样,一个组件就可以并行而安全地安装到计算机上,而它的不同版本安装在各自的应用程序目录中。如果系统上的另一个应用程序要求(并因此安装)一个不同的组件版本,你的应用程序也丝毫不受影响。不同的应用程序都将运行它们各自不同版本的组件。 当另一个应用程序在系统上安装了一个组件的新版本时,你的现存版本的组件将不受影响,因为你把它安装在你自己的应用程序目录下面。你的应用程序将继续使用和这个应用程序一起发布的组件版本,而另一个应用程序则使用它自己的版本。操作系统可以同时载入同一组件的不同版本。 类似地,因为并行组件对安装它的应用程序而言是“私有”的,所以应用程序的卸载程序总是可以安全地移去并行组件,正如定义所表明的那样,没有任何其他应用程序会依赖于一个私有组件。
注意 并行组件必需在操作系统上正确地进行注册(后文将有描述),以便组件的每个版本都不会和可能存在的其它版本产生冲突。 注意 Windows 2000 和 Windows 98第二版都支持并行共享。先前版本的Windows操作系统不支持并行共享;但是,在这些操作系统上,可以将并行DLL(按照下一个部分描述的指导原则编写的DLL)安装到系统目录下。这样,DLL就以一种全局共享(向后兼容)的方式运行。应用程序必需动态地检查操作系统的版本,以决定使用哪一种共享技术。
编写并行组件的指导原则
下面的指导原则概括地描述了在创建并行组件(COM或Win32)过程中涉及的问题。在你编写这样的组件并将它们安装到应用程序目录下时,你的代码就为应用程序的上下文所私有了。当你在注册表的某个应用程序下注册你的数据时,这些数据也将为应用程序所私有。 使用你的并行组件的顾客可以隔离于在其它使用同一组件的顾客的要求下可能对组件所做的改动。你还可以在无须担心破坏现存应用程序的前提下放心地更新你的组件。即使另一个应用程序正在使用你的组件的另一个不同版本,你的应用程序也可以在不需要重新启动计算机的情况下安装你的组件。
注意 这些指导原则比当前让你将Win32 DLL安装到应用程序目录下的Windows认证规范指导原则更为健壮。
一般问题
- 不要试图替换任何被Windows 2000的System File Protection保护的文件,其中包括大多数.sys、.dll、.exe和.ocx文件。
- 你必需测试所有的组件,以保证并行组件的有效性,特别是在共享可能发生的地方,因为当前的操作系统没有对并行运行的强制。
- 将所有与版本相关的变量集中到#define来定义,以便允许源代码可以方便地从一个版本移植到另一个版本。这样做可以让你在一个地方做改动就可以改变组件的版本;之后所有的注册键都会自动改变。例如:
- #define MyRegistryKey "MyAppv1.0.0.0"
当你发布你的组件的一个新版本时,你只需要在一个地方做改动,就可以改变组件的版本。
- 注意到你将会丧失对组件的快速修正能力,因为现在这些组件被安装到主观选定的应用程序目录下。作为一个组件开发商,你可能无法知道到哪里去修正你的组件。而应用程序开发商又不得不向顾客分发更新组件。
- 注意无法预计的进程间共享。例如,共享内存块可能会带来问题,因为共享内存块在组件的不同版本之间是不能共享的。
- 你需要将所有的共享数据结构设计为并行的(随每个不同的组件版本而不同),这包括内存映像文件、互斥文件、命名管道和硬件驱动程序等。
- 你必需把所有临时数据保存在TEMP目录下。
- 不要把用户数据存放在共用路径下。应用程序数据和用户数据之间应当明显地分开。
强化你的组件
- 你必需在全局注册表中适当地处理安装和卸载不同软件开发商创建的组件时组件GUID的引用记数。在GUID键下维护一个引用记数是达到这个目的的最有效的方法。
- HKEY_CLASSES_ROOT\CLSID\{GUID}\InprocServer32
- Default=foo.dll
- ThreadingModel=Apartment
- RefCount=1
注意 你必需将DLL独立于GUID进行引用记数。
- 在注册COM时不要注册全路径;你可以对应用程序目录进行目录查找来找到你的组件以及它的依赖关系。
- 如果你在COM GUID下改动元数据(例如线程模型),那么你必需对你的组件重新命名并使用一个新的GUID,因为此时组件已经有效地成为一个新版本的组件。(由于注册表中的数据在另一个具有自己私有版本的组件的应用程序上下文中将会无效,所以你必需这样做。)
- 你必需在DLL中、而不是在一个单独文件中包含类型库。
- 不要使用LoadRegTypeLib函数来通过注册表装载类型库。注册表中类型库的注册是全局状态,并根据私有规则进行记数。应该使用LoadType Lib。
- OLEAUT创建新版本外部类型库的功能是很脆弱而容易失败的。建议你不要在并行组件中使用外部类型库。
- 当对一个现存组件进行改动来使它成为一个并行组件时,你实际上在改变这个组件被激活的方式,以使用一个相对路径并隔离开组件的全局状态。有一点很重要:你必需为这个组件提供一个新的CLSID,ProgId并将文件重命名。然后,你就可以将这个CLSID,ProgId和新的文件名用于组件将来的并行版本中。这样做可以避免当一个非并行组件和一个并行组件安装在一起时带来的冲突问题。并行组件和先前安装的非并行组件是不兼容的。
状态存储
- 对于存储在注册表中的组件状态(设置),你需要将组件的状态设置为被运行它的应用程序上下文所私有。你可以使用GetModuleFileName()函数来设置一个虚拟根目录。对HKLM和HKCU分枝应当这样设置。
- 应当对每个版本都在注册表中进行设置,以便在注册表里它们是相互隔离的。注册键是一个通常使用的让组件保存它们状态的方法。由于可能在你的机器上存在你的组件的不同版本,所以尽可能容易地在重新编译组件时在注册表中填入相应版本信息显得非常重要。采用一套好的头文件和帮助API可以很容易地达到这个目的。
- 用如下命名规则在注册键中保存你的注册状态:
- HKCU\MyCompany\MyComponent\VersionXXXX\
例如,假设有一个其值为true或false的称为EnableSuperCoolFeature的设置。传统地,你可能在注册表中如下存储这个信息:
HKEY_CurrentUser\Software\MyCompany\MyComponent\
EnableSuperCoolFeature = TRUE
在并行共享情况下,你需要这样来存储这个信息:
HKEY_CurrentUser\Software\MyCompany\MyComponent\Version01.01
EnableSuperCoolFeature = TRUE
- 另外,如果你需要将各个应用程序也隔离开,你可以使用
- HKCU\MyCompany\MyComponent\VersionXXYY\SomeApplication\\
这里的“SomeApplication”是GetModuleFileName的返回值。这样做的结果是允许组件和它的设置隔离到当前它在其中运行的应用程序。
- 理想地,你应当支持一个持续模型,以便让应用程序负责维护你的组件状态,而无须改动注册表。应用程序不应当需要直接访问组件的注册表入口。反之,组件应当提供保存或恢复这些并行兼容的设置的API。
- 为了和全局状态进行交互,存储在注册表以外其它地方的设置应当以一种并行方式存储。这种存储区包括:
· 一个被保护的存储区
· 一个WinInet缓冲区
· 一个Microsoft SQL Server™或Microsoft Jet数据库
安装并行组件
在你安装之前
在你安装并行组件之前,你必需判断它们是否为你的操作系统所支持。下面的代码检查并行共享是否可用。如果并行共享不可用,那么组件必需被安装到系统目录下。
BOOL bPlatformSupportsSideBySide(void)
{
OSVERSIONINFOEX osviex ;
osviex.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
// If platform does not support OSVERSIONINFOEX structure, it does not
// have side by side support
// In the kernel we have made these modifications hand-in-hand...
//
if (!GetVersionEx((OSVERSIONINFO *)&osviex))
{
return FALSE ; // no DLL redirection
}
// However for NT, then NT4 SP4 had support for OSVERSIONINFOEX
// support but it did not support DLL redirection.
// If DLL redirection appears in a future NT4 SP, this code will have
// to be updated.
//
if ( (osviex.dwPlatformId == VER_PLATFORM_WIN32_NT) &&
(osviex.dwMajorVersion < 5) )
{
return FALSE ;
}
// For the other platform Ids, assume has side-by-side support
return TRUE ;
}
安装和卸载
正确地安装和卸载你的组件非常关键。理想情况下,除了将组件拷贝到应用程序目录下和从应用程序目录下移去组件之外,安装和卸载过程应当不再需要其它处理过程。但是,如果你需要对你的组件进行COM注册或任何其它初始化设置的话,那么你必需以一种与并行兼容的方式完成这些动作。 Windows 2000 包括Windows Installer version 1.1。Windows Installer version 1.1将支持并行组件的安装和卸载。(在Windows 2000发布之后,Windows Installer还可以从网上下载。)在注册你的并行COM组件时,你需要确保Class表的Attributes域值的msidbClassAttributesRelativePath位被设置了。这将使组件以一个相对路径注册,从而允许同一个组件的多个副本同时存在。 当你的组件在应用程序目录下为应用程序所私有时,一些其它的应用程序可能已经在这台机器上安装了一个同样组件的不同版本。记住这一点很重要。在安装或卸载这个组件时,你不会希望自己的任何操作破坏其它的应用程序。因此,使用你的组件的应用程序将由你通过自注册入口点DLLRegisterServer或DLLUnregisterServer(对COM组件)或者DllInstall(对Win32或COM组件)来把它正确地安装到机器上。要了解有关这些函数的更多信息,请在Platform SDK”中参看“Registering Server”部分。 要在应用程序目录下正确安装你的组件,则除了安装一个普通组件的步骤之外,你还得完成如下以下步骤:
- 当你注册GUID时,要确保它们都有相对路径名字。
- 确保你的GUID有一个引用记数。
这将帮助你弄清这个GUID安装和卸载的次数。
- 如果GUID已经存在,那么增加你的引用记数
或者 如果它不存在,那么你需要将GUID加入,并把它的引用记数设置为1。例如:
- {00000109-0000-0010-8000-00AA006D2EA4}
- \InprocServer32
- Default = "mycomponent.dll"
- ReferenceCount=1
注意类型库应当包含在你的DLL中,并且无须在系统注册表中进行注册。
要从应用程序目录下正确地卸载你的组件,则除了安装一个普通组件的步骤之外,你还得完成如下以下步骤:
- 减少你的引用记数。如果引用记数减少到0,那么你就知道你可以将GUID删除了,因为再没有其它的用户了。但是,如果引用记数大于0,则表明另一个应用程序被安装到系统上并且它正在使用注册表状态。
DLL/COM重定向
DLL/COM重定向要求在部署应用程序时,应用程序的可执行文件和所有隔离组件都被安装到应用程序目录而不是系统目录下。此外,一个“.local”文件被部署到应用程序目录,以便修改Windows的捆绑行为,这样应用程序就捆绑到隔离组件而不是全局共享版本的组件上。
这样,应用程序将使用一个可以安全地和安装在别处的在另一个应用程序目录或在系统目录下的同一组件的不同版本并行运行的组件。如果系统上的另一个应用程序要求一个不同的版本,那么你的应用程序将丝毫不会受到影响,并且所有的应用程序都将和它们各自版本的组件一起运行。
在另一个应用程序在系统上安装了一个新版本的组件的情况下,这个应用程序中使用的组件的版本将不会受到影响,因为组件是安装在你的应用程序目录下的。你的应用程序将继续使用和你的应用程序一起发布的组件版本,而另一个应用程序则使用它自己的版本。操作系统可以同时在内存里载入同一组件的不同版本。
注意 隔离COM组件必须在操作系统上正确地进行注册,以便组件的每个版本都不会和可能存在的其它版本之间发生冲突。COM组件的注册还要求,虽然在组件的不同版本之间可以对组件的实现代码进行改动,但是一定不能改动如CLSID,Progid,类型库和线程模型等COM注册元数据。
注意 Windows 2000和Windows 98第二版都支持DLL/COM重定向。但是先前的Windows操作系统不支持。
使用DLL/COM重定向
DLL/COM重定向允许开发人员或者管理人员选择性地将现存的组件隔离到它们正在建造和部署的应用程序中。这个部分讨论如何激活DLL/COM重定向,以及如何选择被隔离的组件。
激活DLL/COM重定向
DLL/COM重定向是由一个“.local”文件针对应用程序进行激活的。这个“.local”文件是和应用程序的.exe文件处于同一目录下的一个空文件,文件名和应用程序的.exe文件名一样,只是它在这个文件名后面加上一个后缀.local。
例如,要为一个称为“myapp.exe”的应用程序激活DLL/COM重定向,那么就要在myapp.exe的安装目录下创建一个称为“myapp.exe.local”的空文件。
一旦DLL/COM重定向被激活,则在应用程序装载一个DLL或一个OCX的任何时候,Windows将首先在应用程序的.exe文件的安装目录下寻找相应的DLL或OCX文件。如果在应用程序的.exe文件安装目录下找到了一个版本的DLL或OCX,那么应用程序将使用这个版本的DLL或OCX,而不管应用程序中或注册表里标示的任何其它目录路径。如果在应用程序的.exe文件安装目录下找不到任何版本的DLL或OCX,则将执行正常的路径搜索,或使用服务器路径。
选择隔离组件
当安装在一个计算机上的应用程序要求同一组件的不同版本时,DLL/COM重定向允许隔离现存的组件。这个过程不要求任何对组件代码的改动,因为,一旦被激活,DLL/COM重定向将改变Windows的捆绑行为。
但是,组件不同版本的并行执行到目前为止仍然没有成为一个典型的在设计上的考虑。虽然组件可以很容易地并行安装(安装在一个共享路径下并隔离到一个或多个应用程序),但是它们可能并不可以并行运行。这种情况的出现是因为一些组件使用全局状态(例如存储在注册表中的设置),并且它们假设在任何时候,计算机上都仅仅有组件的一个版本。此外,组件可能还会假设它被安装的路径是某个路径,并通过这种假设来找到它需要的资源。
由于这个原因,所以测试一个使用隔离组件的应用程序变得非常必要。这个隔离组件可能是单独安装的,也可能是和某个使用它的应用程序一起安装的。微软公司的经验表明,在大多数情况下,一般的共享组件可以并行运行,但是在某些情况下,需要在运行下一个应用程序之前关闭一个当前运行的应用程序。
在选择被隔离的组件时,应当遵循下面这些指导准则:
- 不要试图替换任何被Windows 2000的System File Protection保护的文件,其中包括大多数.sys、.dll、.exe和.ocx文件。
- 你必需测试所有的组件,以保证并行组件的有效性,特别是在共享可能发生的地方,因为当前的操作系统没有对并行运行的强制。
- 注意到你将会丧失对组件的快速修正能力,因为现在这些组件被安装到主观选定的应用程序目录下。作为一个管理人员,你需要知道到哪里去修正你的组件。
场景I:使ActiveX控件为一个应用程序所私有
在这种场景下,管理人员将无法部署一个新的应用程序,因为新的应用程序使用用Visual Basic编制的ActiveX控件版本,这个版本和当前已经部署的应用程序使用的控件版本不一样。 随着时间的推移,对缺陷的修正和对ActiveX控件的其它修改会引入语义差别,这样,如果应用程序使用的版本和它在测试时使用的版本不相同的话,那么使用这个控件的应用程序将无法正常工作。管理人员需要能够运行同一ActiveX控件的不同版本和使用这个ActiveX控件的不同应用程序,并避免修正和重新测试每一个可能受变化后的ActiveX控件影响的应用程序的工作。
注意 在Visual Basic里,没有简单易行的方法可供开发人员用来编写具有固有并行特性的ActiveX控件。这是因为对用Visual Basic编写的ActiveX控件进行注册时,将会在注册表里写入OCX文件的全路径。 管理人员可以强制新的应用程序使用ActiveX控件的正确版本,并可以确保现存应用程序的配置不发生任何改变。这是通过将新应用程序的安装过程修改为下面的样子来达到的:
- 将新版本的ActiveX控件安装到应用程序的.exe文件所在的路径下。
- 在应用程序的.exe文件所在的目录中,安装一个.local文件,以表明当应用程序运行时,ActiveX控件应当从应用程序的.exe文件所在的目录中载入。
场景II:使Win32 DLLs为一个应用程序所私有
在这个场景中,管理人员获悉一个现存应用程序在一个新的应用程序部署之后停止正常工作了。管理人员可以诊断出这个问题是由于对一个共享组件的改动引起的,并且这种改动导致新版本的共享组件不向后兼容组件的先前版本。
管理人员可以通过采取如下步骤对应用程序进行修正:
- 将先前版本的共享DLL安装到现存应用程序的.exe文件所在的目录下。
- 在现存应用程序的.exe文件所在的目录下创建一个.local文件。这个.local文件表明,在应用程序运行时,位于现存应用程序的.exe文件所在目录下的DLL应当首先被装载。
安装隔离COM Server时的考虑
DLL/COM重定向是通过在一个新的路径下安装应用程序私有的DLL或者OCX文件来达到的。但是,其它和COM Server有关的对隔离COM Server有一些特定含义的系统状态将无法被隔离。 在安装一个隔离COM Server时,应当注意保证如果计算机上已经安装了某个组件的任何不同版本(例如,由另一个应用程序安装的版本)的话,那么InprocServer文件路径不能被隔离组件的新路径覆盖。对于隔离COM Server而言,InprocServer文件路径在运行期间是被忽略的。但是,不使用DLL/COM重定向的现存应用程序要求继续使用InprocServer文件路径来确定先前安装的COM Server的路径。这一点的含义如下:
- 在安装一个隔离COM Server时,如果COM Server的任何版本已经安装到计算机上的话,那么不要在安装期间注册隔离COM Server。
相反地,如果COM Server的某个版本没有安装到计算机上,那么它必需在安装期间进行注册。在这里,可能产生问题的场景是当一个COM Server被隔离到一个应用程序并且被安装到应用程序的.exe文件所在目录,之后再安装需要这个组件的一个非隔离应用程序时。在这种情况下,隔离应用程序的卸载程序不太可能将这个隔离COM组件作为一个共享文件看待,并且卸载将会使其它的应用程序无法正常运行。这一点的含义如下:
- 在安装一个隔离COM Server时,如果在计算机上没有安装这个COM Server的任何版本,那么将DLL或OCX文件同时复制到应用程序的.exe文件所在目录以及系统目录(或者其它共享目录),然后将系统目录(或者其它共享目录)中的DLL副本进行注册。
对有些版本被一些应用程序共享而另一些版本被某些应用程序私有的现存组件,一个合理的经验法则如下:在安装了使用可能会被共享的组件的隔离版本的应用程序之后,要确保组件的共享版本和隔离版本都被安装到计算机上,并且对共享版本进行了注册。这样做就允许卸载程序在无须担心影响其它应用程序的正常运行的前提下放心地移去组件的隔离版本。
|