ado|数据利用 .NET 框架简化发布和解决 DLL Hell 问题
Steven Pratschner
Microsoft Corporation
2000年9月
摘要: 本文介绍汇编概念并说明 .NET 框架如何使用汇编解决版本和发布问题。
目录
简介
问题叙述
解决方案的特性
汇编:积木
版本与共享
版本策略
发布
摘要
--------------------------------------------------------------------------------
简介
Microsoft® .NET 框架介绍了几个新功能,旨在简化应用程序发布和解决 DLL Hell。最终用户和开发人员都熟悉版本和发布问题,这些问题会伴随着如今基于组件的系统一同出现。例如,每个最终用户都在他们的机器上安装了一个新的应用程序,没料到已有应用程序神秘地停止了工作。多数开发人员花费时间使用 Regedit,努力保持所有必要的注册项一致以便激活 COM 类。
.NET 框架中用于解决 DLL Hell 问题的设计原则和实现技术是建立在 Microsoft Windows® 2000 的基础上的, Rick Anderson 所著的 The End of DLL Hell(英文)和 David D'Souza, BJ Whalen 及 Peter Wilson 所著的 Implementing Side-by-Side Component Sharing in Applications (Expanded) (英文)中都有说明。.NET 框架提供的许多功能都在这两篇文章中有所描述,包括应用程序隔离和并行组件,用于建立在 .NET 平台的应用程序。您将了解 .NET 平台上提供的版本支持,它能使本地 Windows 应用程序更紧密地汇集。
本文介绍了汇编的概念,并描述 .NET 如何使用汇编来解决版本和发布问题。我们将特别讨论汇编如何构建,如何命名以及编译器和通用语言运行时如何使用汇编来记录和加强应用程序片段间的版本依赖。我们也将讨论应用程序和管理员如何能通过我们所称的版本策略定制版本行为。
介绍并说明了汇编后,将展示几个发布方案,以便使您对 .NET 框架中提供的各种打包和分发选项多少有一些了解。
--------------------------------------------------------------------------------
问题叙述
版本
从客户的角度,最常见的版本问题就是我们所说的 DLL Hell 问题。简单地讲, DLL Hell 是指当多个应用程序试图共享一个公用组件(如某个动态连接库(DLL)或某个组件对象模型(COM)类)时所引发的一系列问题。最典型的情况是,某个应用程序将要安装一个新版本的共享组件,而该组件与机器上的现有版本不向后兼容。虽然刚安装的应用程序运行正常,但原来依赖前一版本共享组件的应用程序也许已无法再工作。在某些情况下,问题的起因更加难以预料。比如,当用户浏览某些 Web 站点时会同时下载某个 Microsoft ActiveX® 控件。如果下载该控件,它将替换机器上原有的任何版本的控件。如果机器上的某个应用程序恰好使用该控件,则很可能也会停止工作。
在许多情况下,用户需要很长时间才会发现应用程序已停止工作。结果往往很难记起是何时的机器变化影响到了该应用程序。用户可能会回忆起一周前安装了一些东西,但安装与目前看到的状态并没有任何明显的关联。 更糟的是,现在很少有诊断工具帮助用户(或帮助他们的技术支持人员)确定有什么问题。
这些问题的原因是应用程序不同组件的版本信息没有由系统记录或加强。而且,系统为某个应用程序所做的改变会影响机器上的所有应用程序—现在建立完全从变化中隔离出来的应用程序并不容易。
很难建立一个隔离应用程序的一个原因是当前运行时环境只允许单独版本组件或应用程序的安装。这个限制意味着组件的编写者必须以向后兼容的方式编写他们的代码,否则当他们安装新组件的时候会有终止已有应用程序的风险。实际上,如果可能的话,编写永远向后兼容的代码是非常难的。在 .NET 中,side by side 概念是版本问题的核心。"Side by side" 是在同一台机器上同时运行不同版本的相同组件的能力。使用支持并列的组件,编程人员不必努力维护严格的向后兼容,因为不同的应用程序自由使用某个共享组件的不同版本。
发布和安装
现在安装应用程序是多步过程。一般,安装一个应用程序包括复制许多软件组件到磁盘,和在系统中进行一系列描述那些组件的注册项。
注册表中的项和磁盘上文件的分隔使复制应用程序和卸载他们非常困难。而且,在注册表中完全描述某个 COM 类所需的许多项之间关系非常松散。这些项常常包括联合类、接口、类型库和 DCOM app ID 的项,不涉及任何放在注册表文档扩展或组件类别的项。要时常手工保持这些项的同步。
最后,需要该注册足迹激活任何 COM 类。这极大地复杂了发布分布式应用程序的过程,因为必须到每个客户端的机器进行适当的注册项。
如今另一个共同问题是:对一个正在运行的应用程序进行更新是不现实的。这是 Web 应用程序最大的问题,Web 应用程序必须停止工作然后重启动以更新应用程序使用的 COM 类。
这些问题主要由从组件自己分离传来的组件描述引起的。换句话说,应用程序不是自描述的和独立的。
--------------------------------------------------------------------------------
解决方案的特性
.NET 框架必须提供以下基本的能力解决刚刚描述的问题:
应用程序必须是自描述的:自描述的应用程序去掉了对注册表的依赖,能够毫无影响的安装和简单的卸载和复制。
必须记录和加强版本信息:版本支持必须建立在平台内部以保证依赖的适当版本在运行时载入。
必须记得“上次已知的正确配置”:当应用程序成功运行时,平台必须提供记住这套一起工作的组件的能力—包括它们的版本—。
必须支持并列组件:允许多个版本的组件同时安装和运行在机器上,允许调用者指定他们需要载入的版本代替不知不觉被强迫的版本。.NET 框架通过允许框架自己的多个版本同时存在于一台单独的机器上使并列邻先了一步。这极大地简化了升级问题,因为管理员如果需要可以选择运行不同版本 .NET 框架上的不同应用程序。
必须使应用程序隔离: .NET 框架必须简化(实际上已经默认)编写不受机器上其他应用程序的改变影响的应用程序。
--------------------------------------------------------------------------------
汇编:积木
汇编是 .NET 框架用于解决刚描述的版本和发布问题的积木。汇编是类型和资源的发布单元。在许多方面汇编和现在的 DLL 相同。从本质上讲,汇编是“逻辑 DLL”。
汇编是通过元数据调用清单自描述的。就像 .NET 使用元数据描述类型一样,它也使用元数据描述包含类型的汇编。
汇编不仅仅于发布有关。例如,.NET 中的版本在汇编层完成 —没有任何减少,就像一个模块或类型的版本化。而且,汇编还用于在应用程序之间共享代码。包含某个类型的汇编是该类型标志的一部分。
访问安全系统的代码在其许可模型的内核中使用汇编。汇编的编写者在清单中记录一组运行该代码所需求的许可,然后管理员将许可授权给基于汇编的代码,此汇编包含该代码。
最后,汇编也是类型系统和运行时间系统的核心,在其中他们为类型和服务建立了一个可视的边界作为解决引用类型的运行时间范围。
汇编清单
清单明确包括以下有关汇编数据:
标识:一个汇编标识由三部分组成:名称、版本号和选项文化。
文件列表:清单包括所有组成汇编的文件列表。对于每个文件,在建立清单时记录它的名称和内容的加密信息。该信息在运行时验证以确保发布单元的一致。
引用的汇编:汇编间的关系保存在收集的汇编清单中。从属信息包括版本号,它用于运行时保证载入正确版本的关系。
输出类型和资源:对类型和资源可用的可视选项包括“仅在我的汇编中可视”和“对我的汇编之外的调用者可视。”
许可需求:汇编许可需求分为三组:汇编运行需求、需要的但汇编还有一些即使没授权的功能的需求,以及编写者不想汇编被授权的需求。
IL 反汇编 (Ildasm) SDK 工具对于在汇编中查看代码和元数据很有帮助。图 1 是一个以 Ildasm 现实的范例清单。.assembly 表示汇编而 .assembly extern 包含有关其他汇编所依赖的信息。
图 1. 以 IL 反汇编显示的范例清单
汇编结构
到此为止,汇编主要以逻辑概念描述。本节通过描述他们如何在物理上体现帮助您使汇编更加具体。
通常,汇编由四个元素组成:汇编元数据(清单)、元数据描述类型、实现该类型的媒介语言 (IL) 代码和一组资源。不是所有的这些都出现在每个汇编中。只有清单是严格需要的,但类型或资源需要给汇编一些重要的功能。
有几个关于这四个元素能如何包装的选项。例如,图 2 表示包含整个汇编:清单、类型元数据、IL 代码和资源。
图 2. 包含所有汇编元素的 DLL
另一种情况,一个汇编的内容也许分割为多个文件。在图 3 中,作者选择将一些有用的代码分离到一个不同的 DLL 中,并在它的原始文件中保留一个大的资源文件(这里是一个 JPEG 文件)。这样做的一个原因就是优化代码的下载。.NET 框架只在引用时才下载文件,所以如果汇编包含经常被访问的代码或资源,那么将他们分成单独的文件将提高下载的效率。
图 3. 汇编元素分割为多个文件
--------------------------------------------------------------------------------
版本与共享
DLL Hell 一个主要目的就是共享当前在基于组件的系统中使用的模型。默认情况下,单独的软件组件由机器上的多个应用程序共享。例如,每次一个安装程序复制一个 DLL 到系统目录或在 COM 注册表中注册一个类,该代码将潜在地影响其他运行在机器上的应用程序。实际上,如果一个已存在的应用程序使用共享组件的前一个版本,那么该应用程序将自动使用新版本。如果共享组件是严格向后兼容的这当然更好,但如果不可能,在许多情况下维护向后兼容是很困难的。如果没有维持向后兼容或不能维持,作为其他应用程序安装时的侧面影响经常导致应用程序中断。
.NET 设计方针的一个原则就是隔离组件(或汇编)。隔离一个汇编的意思是一个汇编只能由一个应用程序访问—不是由机器上的多个应用程序共享并且不可能因其他应用程序对系统的改变而影响。隔离赋予开发者对应用程序所用代码的绝对控制。隔离,或应用程序专用汇编期望在 .NET 应用程序中是默认的。隔离组件的趋势在 Microsoft Windows 2000 中随着 .local 文件的引入已经开始。该文件用于努力定位所需组件时使 OS Loader 和 COM 首先从应用程序目录查找。(请参阅 MSDN Library 中的相关文档,Implementing Side-by-Side Component Sharing in Applications(英文)。)
然而,有些情况下在应用程序之间共享汇编是必要的。很明显每个应用程序都有自己的 System.Winforms、System.ASP 或公用的 Web 表格控件的副本是没有意义的。
在 .NET 中,在应用程序之间共享代码是明确的决定。共享汇编需要一些附加的需求。特别是,共享汇编应该支持相同的汇编并排多个版本安装和运行在相同的机器上,或者甚至在相同的进程中,在相同的时间。另外,共享汇编有更严格的命名需要。例如,一个共享的汇编必须有一个全局唯一的名称。
隔离和共享的需要导致我们考虑两种汇编。这是个相当松散的集合,在这两种汇编之间没有实际的结构,但它们如何使用是不同的:专用于某个应用程序或与许多应用程序共享。
应用程序专用汇编
应用程序专用汇编是只对某个应用程序可视的汇编。我们期望这是 .NET 应用程序最普通的情况,因为 .NET 框架帮助建立从其它应用程序引起的系统变化中隔离的应用程序。
专用汇编的命名需求很简单:汇编名称必须在应用程序中是唯一的。没必要起全局唯一的名称。保持名称唯一不是问题因为应用程序开发者完全控制哪个汇编与应用程序隔离。
应用程序专用汇编部署在使用它们的应用程序目录结构中。专用汇编可以直接放在应用程序的目录或它的子目录中。通用语言运行时间通过称为 probing 的进程查找这些汇编。"Probing" 是汇编名称到包含清单的文件名称之间的简单映射。
特别地,通用语言运行时间把汇编的名称记录在汇编引用中,追加“.dll” 并在应用程序的目录中查找该文件。该方案中有一些变量,在那里运行时间会访问汇编命名的子目录中或汇编的风格命名的子目录。例如,某个开发者会选择将包含定位于德国的资源的汇编部署在称为“de”的子目录中,并将西班牙的资源部署在称为“es”的子目录中。
如前所述,每个汇编清单包括有关其关系的版本信息。该版本信息没有为专用汇编而加强,因为开发人员完全控制了部署到应用程序目录的汇编。
共享汇编
.NET 框架还支持共享汇编的概念。共享汇编是在机器上由多个应用程序使用的。使用 .NET,共享应用程序之间的代码是明确的决定。共享汇编有些额外的需求用于解决现在我们经历的共享问题。除了支持早先描述的并列之外,共享汇编还有许多严格的命名需求。例如,共享汇编必须有一个全局唯一的名称。而且系统必须提供“名称保护”—更确切的说,防止有人再使用编写者的汇编名称。例如,假设您是一个网格控件的厂家,并且发布了您的汇编版本 1。做为编写您需要确信没有其他人能发布声称为版本 2 的汇编或您的网格控件。.NET 框架支持通过称为共享名的技术支持支持这些命名需求。(在下一节详细说明)。
通常,应用程序编写者不对应用程序使用的共享汇编有同等程度的控制。结果,在每次引用共享汇编时都检查版本信息。另外,.NET 框架允许应用程序和管理员通过指定版本策略重载应用程序使用的共享汇编版本。
共享汇编通常部署到全局汇编库。全局汇编库是供多个应用程序使用的机器范围的汇编库。使用该库不是必要条件,但这样做有很多好处。例如,自动提供多个版本的汇编并行存储。而且,管理员能使用该库部署他们需要的每个机器上的应用程序要使用的缺陷修复或安全补丁。在该方案中,配置汇编到全局汇编存储能影响机器上的多个应用程序。.NET 框架利用版本政策(稍候描述)的概念解决了现在出现在系统中共享区域的问题,例如 %windir%\system32。
在库中添加汇编需要明确的管理员操作—实际上,安装过程必须有“管理员权限”。汇编从不在存储结束作为运行一个应用程序的侧面影响,也不是当前工作的共享汇编的任何存储。在 Visual Studo .NET 时间框架中,Windows 安装程序将更新为理解汇编和汇编库。这意味着可以使用 Windows 安装程序的所有功能,例如使用 .NET 应用程序选择安装和应用程序恢复。
.NET SDK 包括两个用于汇编库的工具。第一个是称为 AL 的工具,它允许在库中添加汇编。AL 使开发和测试方案变得方便,它不需要创建整个 Windows 安装程序包在库中添加一个汇编。使用 /install 开关在库中添加汇编:
Al /install:myassembly.dll
第二个工具是 Windows Shell Extension,它允许您使用 Windows Explorer 操作库。图 4 表示全局汇编库的视图。
是不是这个:ADO+ 引导数据种类的演变 (转自 ms 一)
80酷酷网 80kuku.com