版本与共享 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
图 4. 全局汇编库 共享名 共享名用于使严格的命名需求与共享汇编结合起来。共享名有三个目标: 名称唯一:共享汇编必须具有全局唯一的名称。
该方案是称为“Main”的汇编,它引用一个称为“MyLib”的汇编。MyLib 具有共享名。重要的步骤如下所述。
开发者调用在密钥对中传递的编译器和一组汇编的源文件。密钥对通常由称为 SN 的 SDK 工具生成的。例如,下面的命令生成一个新的密钥对并保存的文件中: Csc /t:library math.cs /a.keyfile:MyKey.snk /a.version:1.0.0.0
术语“签名”常常联想到 Microsoft Authenticode。理解共享名和 Authenticode 没有任何关系是非常重要的。这两个技术有不同的目标。实际上,Authenticode 意味着对发行者信任的水平,而共享名不是。没有与强名称相关联的授权许可或第三方签名授权。另外,共享名签名通常由编译器本身作为编译过程的一部分进行。但是,也有实用程序用于在 SDK 中签名。 另一个值得考虑的是“测试签名”工程。汇编的编写者经常不能访问需要完全签名的专有密钥。大多数公司很好的保护这些密钥的存储它只能被少数人访问。结果,.NET 框架提供少量在开发中的“测试签名”技术,然后再“真实签名”。
如刚刚所描述的,每个汇编清单记录它创建所依赖的每个关系的版本信息。但是,有一些方案应用程序的编写者或管理员需要在运行时以关系的不同版本运行。例如,管理员应该能发布故障排除版本而不需要重新编译每个应用程序以便得到该修改。而且,管理员必须能列出因发现安全漏洞或服务故障从没有使用的汇编的详细版本。.NET 框架通过版本策略在版本绑定中启用了该灵活性。 汇编版本号 每个汇编都有四个部分组成的版本号作为它标识的一部分(就是说,一些汇编的版本 1.0.0.0 和 版本 2.1.0.2 是完全不同的与类装载器有关的标识)。包括作为标识的一部分的版本主要用来区分用于并行目的的汇编的版本。 开发人员和管理员必须理解版本号的结构,因为它是通用语言运行时间如何加强汇编之间的版本关系的关键。
图 6. 汇编版本号的四个部分 版本号的几个部分是主要版本、次要版本、内部版本和修订版本。主要版本或次要版本的改变可认为是不可兼容的改变。例如,开发人员改变了一些方法参数的类型或彻底删除了一些类型。类装载器使用该信息使所依赖汇编的不兼容版本不默认载入。 另一方面,仅改变版本号中的建立和版本部分可认为是兼容的。这些改变一般是故障排除或安全补丁,在这种情况下类型定义没有在某种程度上中断调用者的改变,这是兼容的。这些兼容的变化经常称为 Quick Fix Engineering (QFE) 修复或动态修复。 默认的版本策略 当通用语言运行时间遇到在代码中引用汇编时,它决定载入所依赖汇编的版本。默认情况下,载入解决引用的汇编必须有与引用中的记录相同的主版本号和次版本号。如果这些号码不同,该汇编认为是不兼容的,并且不会默认载入。相反,通用语言运行时间会用最高的号码得到 QFE (或动态修复)。 例如,如果 Main 以 MyLib 的 1.0.0.0 版本编译,当运行发现 MyLib 的 1.0.1.1 版本时,将载入 1.0.1.1。 总是取最新的编译和版本的策略称为“自动 QFE 策略”。该原则的主要目的是允许管理员在不重新创建所有应用程序的情况下发布故障排除版本。 定制版本策略 有些时候前面描述的默认策略并不是您所要的。例如,也许应用程序被所安装的 QFE 不经意地中断了。 默认的版本策略能通过使用 XML 配置文件修改。关于版本,有两个文件:一个应用程序说明文件和一个机器范围或管理员文件。应用程序说明文件保存在与应用程序相同的目录中。该文件中的策略描述只影响该应用程序。机器范围策略文件当前保存在 Windows 目录。该文件被管理员用来描述影响本机器上所有应用程序的策略。例如,也许某个管理员确定了某个汇编的详细的版本具有一些安全漏洞,并且他确保该汇编将不再被使用。 自定义策略的示例包括: 绑定指定的版本 有时需要绑定一个与清单记录的版本完全不同的汇编。通过在配置文件中的<BindingPolicy>标签提供对该方案的支持。该策略用于映射某个关系指定版本的引用或某个关系所有版本的引用。 下面例子映射某个称为 Calcr 的汇编 6.0.0.0 版本的引用: <BindingPolicy> 关闭自动 QFE 策略 该策略允许停止“自动 QFE 策略”引用已提供的汇编。 <BindingPolicy> 标签也用在这里,但 UseLatestBuildRevision 属性设置为 No,如下面例子所示: <BindingPolicy> 安全模式 安全模式(或编译运行)策略用于恢复编译配置。启用该策略将使通用语言运行时间载入记录在清单中的关系的一个精确版本。大概应用程序在它创建、测试并第一次发布时工作。安全模式是用于恢复到该状态安全的网络。下面的 XML 代码为具体的应用程序打开安全模式: <BindingMode> 如果某个具体的关系不符合版本规则或不经意引入一个错误,“安全模式”和“关闭自动 QFE 原则”可用于恢复应用程序到某个工作的状态。 策略解决方案中的阶段 本文已经介绍了几个版本和发布的概念,包括应用程序专用汇编、共享的汇编、全局汇编存储和用于指定版本策略的 XML 文件。本节通过描述通用语言运行时间查找汇编和应用版本策略经历的阶段将这些概念连接起来。 当通用语言运行时间遇到引用存储在元数据中的另一个汇编时,开始载入汇编的过程。根据引用,下面的步骤决定载入那个汇编的哪个版本: 参考应用程序说明文件查看是否指定了策略。如果是,以策略的信息修改原始文件。例如,如果引用指定版本 1.0.0.0 而应用程序说明策略文件指定版本 2.0.0.0,通用语言运行时间将按照如同初始指定版本 2.0.0.0 一样处理。
--------------------------------------------------------------------------------
发布包含至少两个不同的方面:包装代码和将这些包装分布给运行该应用程序的客户端和服务器。.NET 框架主要的目标是通过毫无影响的安装简化发布和复制发布的可行性。汇编自描述的天性使我们摆脱对注册表的依赖,因此使安装、卸载和复制变得相当简单。但是,有几种场合下复制作为发布机制并不充分。在这些情况下,.NET 框架提供扩展代码下载服务并集成在 Windows 安装程序中。 包装 在 .NET 框架的第一个版本中有三个包装选项可用: As-built(DLL 和 EXE)。在许多场合,不需要特别的包装。应用程序以发布工具制造的格式发布,即 DLL 和 EXE 的集合。
.NET 应用程序能以多种方式发布,包括复制、代码下载以及通过 Windows 安装程序。 对于许多应用程序,包括 Web 应用程序和 Web 服务,发布和复制一组文件到磁盘并运行一样简单。卸载和复制就像删除这些文件或复制它们一样容易。 .NET 框架提供使用 Web 浏览器下载代码的支持。该部分有几个重要问题,包括: 零影响:没有注册表项添加到机器上。
|
温馨提示:喜欢本站的话,请收藏一下本站!