学习笔记《.NET框架程序设计(修订版)》--第三章 共享程序集 (1)
2004-12-27
第二章里讲到对程序集的私有部署方式。这章里探讨创建可以被多个应用程序共同访问的程序集,即全局部署程序集(globally deployed assembly)。
3.1 两种程序集、两种部署方式
1、.NET 框架支持两种程序集:强命名程序集(strongly named assembly)和非强命名程序集。
强命名程序集有一个发布者的公钥/私钥对签名,其中的公钥/私钥对唯一地标识了程序集的发布者。利用公钥/私钥对我们可以对程序集进行唯一的标识、安全策略和版本策略。
2、一个程序集有两种部署方式:私有方式和全局方式。
非强命名程序集只能进行私有部署。
全局部署方式将程序集部署在一些CLR确知的地方,当CLR搜索程序集时,它会知道到这些地方去查找。强命名程序集既可以进行私有部署,也可以进行全局部署。
3.2 强命名程序集
1、由于简单地用文件名导致了目前所谓的DLL Hell,强命名程序集就是CLR用来唯一地标识一个程序集的机制。
一个强命名程序集包含四个唯一标识程序集的特征:文件名(无扩展名)、版本号、语言文化标识及一个公有密钥标记(它是公有密钥产生的一个值)。
利用 System.Reflection.AssemblyName 类,可以创建一个程序集,并获取一个程序集名称的各个部分。
2、创建一个强命名程序集首先得有一个密钥,这个密钥可以用强命名实用工具(SN.exe,Strong Name Utility)产生SN.exe的所有命令行开关都是区分大小写的。
例子:
SN –k MyCompany.keys
创建一个名为MyCompany.keys的文件,文件中包含一对以二进制格式存储的公有密钥和私有密钥。
查看公有密钥,现以-p命令开关创建一个只包含公有密钥的文件:
SN –p MyCompany.keys MyCompany.PublicKey
然后以 –tp 命令开关查看:
SN –tp MyCompany.PublicKey
公钥非常大,为了方便开发人员(及终端用户),公有密钥标记(public key)应运而生。公有密钥标记是一个64位的公有密钥散列值。SN.exe 的 –tp 命令行开关在输出的末尾显示了和完整公有密钥相对应的公有密钥标记。
3、有了公钥/私钥对,只需把 System.Reflection.AssemblyKeyFileAttribute 特性的一个实例应用到源代码中就可以创建强命名程序集了:
[assembly:AssemblyKeyFile(“MyCompany.keys”)]
编译器在源代码中遇到该特性时,将打开其中制定的文件 MyCompany.keys ,用私有密钥对程序集进行签名,并将公有密钥嵌入到清单中。只有包含清单的那个PE文件被签名,其他文件时不能被显式签名的。
4、签名过程:
程序集的FileDef清单元数据表(参见2.3的2)包含组成该程序集的所有文件的一个列表,每个文件名称被加入到该清单中时,文件内容被转换成一个散列值,该散列值将和文件名一起存入FileDef表中。(默认散列算法时SHA-1,可以用 AL.exe 的 /algid 命令或应用于程序集上的 System.Reflection.AssemblyAlgorithmIdAttribute 定制特性来改变默认的算法);
生成包含清单的PE文件后,该PE文件的整个内容被转换为一个散列值(使用的算法总是SHA-1,不能改变),该散列值经由发布者的私有密钥签名,生成的RSA数字签名被存储在PE文件的一个保留区域(不包括在散列值的计算中)。最后,PE文件的CLR表头被更新以反映数字签名在文件中的嵌入位置(?在PE文件中的偏移值?)。
另外,发布者的公有密钥也被嵌入到PE文件的AssemblyDef清单元数据表中。
5、如果程序集应用到其他程序集的类型和成员,编译器就会在生成的托管模块中嵌入一个AssemblyRef元数据表。该表的每个条目标识的被引用的程序集也有其公有密钥信息,因为公有密钥过大,为了节省存储空间,这个元数据表存储的只是被引用程序集的公有密钥标记而不是完整的公有密钥。
3.3 全局程序集缓存
1、如果一个程序集被多个应用程序访问,那么该程序必须被放在一个CLR已确知的目录下,且CLR在探测到对该程序集的应用时,它必须能自动到该目录下寻找这个程序集。这个已确知的目录叫做全局程序集缓存(Global Assembly Cache,即GAC),它通常位于下面目录中:
C:\Windows\Assembly\GAC
GAC是一个结构化的目录,它包含许多子目录。我们可以调用 GACUtil.exe(安装强命名程序集最常见的工具)并指定 /i 命令开关来将一个强命名程序集安装到GAC中,也可以指定 /u 命令开关将程序集从 GAC中卸载。(/i /u 命令开关适合于开发人员在测试环境中使用,在世界生产环节推荐使用 /ir /ur 开关)
安装.NET框架时,安装程序会同时安装一个【资源管理器】shell扩展程序(shFusion.dll),它能清楚友好地显示GAC的内容。用它打开 c:\Windows\Assembly 目录下,就可以看到安装到GAC中的程序集。
3.3.1 GAC的内部结构
GAC的目的就是为在强命名程序集和子目录间维持一个关系。同一个公司的同一程序集的不同版本在这里存放在不同的目录下。
(把要共享的程序集都装在GAC里头,那得有一个很大的硬盘专门放这个目录了,GAC如果和.NET一起装起来的那这个硬盘分区一定得是系统分区,以前给系统一个相对小的分区的习惯得改改了。不知道GAC可不可以放在其他目录下?。下雪了,天冷,家里没打暖气手僵,赶快去躺被窝,下次接着写这章)