GAC--全局程序集缓存和SN.EXE工具
BizTalk项目做了大半年,每个项目都用到了GAC和SN工具,当时只是"师傅"的大概的讲了下知道它们的作用,即DLL要共享,谁都能快速的访问,则将DLL加上签名并安装到全局缓存,而SN.EXE则是生成密匙文件等的工具.今天刚好没事就网上查找些文章完善总结下相关的知识.
全局程序集缓存 (GAC) 是一种代码缓存,它在任何带有已安装的 CLR 的机器上都可用.旨在跨应用程序共享的程序集可以存储在这里,而其必须有一个强名称.注意,安装了GAC的程序集必须有匹配的程序集名称和文件名,不包括文件扩展名(因此 MyAssembly 必须与 MyAssembly.dll 或 MyAssembly.exe 配对).
DLL地狱
Windows应用程序经常受到动态链接库的拖累,这就是"DLL地狱"问题,在遇到此类麻烦的时候,应用程序的某一个组件会被其他应用程序的不兼容组件覆盖,结果令受到干扰的应用程序完全不能正确工作.这些问题很难诊断出来,因为它们只有在问题组件安装一段时间之后才会突然冒出来.Visual Basic应用程序的DLL地狱问题更是臭名昭著,因为用Visual Basic语言开发的应用程序相比其他编程语言开发的应用程序具有更大程度的外部相关性.微软推出的.NET计划有望采用一种新型的分布单元assembly(装配)来缓和这一严重问题.
assembly机制
assembly机制初探
从编程的角度来看,一个assembly在功能上等同于Java包:它提供了相关类的可分配库而且定义了它们的范围.对那些不熟悉Java的人来说,在开发应用程序的时候,assembly之于.NET无异于DLL文件之于COM,只不过assembly由多个文件所组成.
Assembly可以通过所谓的名单(manifest)实现自我文档化,这也是它们相比DLL更为优异的一个典型特征.名单包含在assembly之内,由说明assembly的导出类的元数据、这些类所需的外部依附、使用assembly所需的权限以及此类依附的版本控制信息所组成.在.NET框架内,assembly为版本、类以及不能版本化的单个文件提供了公共名称.这样就可以不必检查多个文件以确定系统上安装组件的版本,这也正是我们以往最感到气恼的地方..NET的这种版本控制特性几乎可以完全消除DLL地狱病.
私有assembly和公共assembly
在缺省的情况下,.NET的assembly是私有的,这意味着它们仅能被某一个应用程序所用.私有的assembly应当被安装到应用程序所在的文件夹或其子文件夹之一.微软希望大多数 .NET开发人员能采用私有的assembly,而事实上它也在鼓励人们这样做.
但是,这样会带来一个潜在的问题:用户的硬盘内可能因为拥有同一私有assembly的多重拷贝而变得混乱不堪,这真是很具有讽刺意味,听起来反倒是COM好象更容易解决这个问题了.微软则是这样回应以上批评的:"硬盘很便宜,买个更大的就行了."幸好,你可以非常方便地把私有的assembly转为公共assembly,甚至不必重新编译或编辑代码.
共享之美
共享assembly和私有assembly之间的主要差别在于前者通常保存在专门命名的全局装配缓存(简称GAC)内.GAC有时在微软文档中被称为Global Assembly Store,可能是因为后者简称起来好听一些.
GAC能存储同一assembly的多个版本,这就是微软所称的"肩并肩部署"功能.这一功能几乎消除了安装应用程序的不兼容共享组件而影响其他应用程序的可能性,这对开发者来说肯定是个好消息.
客户assembly能指定它兼容哪个或者那些共享assembly的版本.如果客户程序的版本要求不能被满足,那么.NET运行时就不会装载任何服务器assembly.顺便说一句,.NET的assembly版本由4位数字格式表示,形式如:主版本号.次版本号.创建版本号.修订版本号.
默认地.一个assembly被认为只能兼容具有同样主版本和次版本号的共享assembly.然而运行时装载器却优先装载相比客户版本具有更高创建版本号或者修订版本号的assembly,如果存在这样的assembly,就会自动地为其提供修补支持.这种缺省行为并不一定总是你所希望的,因此程序员或系统管理员可以定义定制的版本控制策略,比方说,强迫装载某一特定的版本或者禁用装载器对更高创建版本号或者修订版本号的assembly的装载.
在Beta 1版上,版本控制策略包含在一些XML文件内,而这些文件则要不驻留在应用程序目录下要不就保存在Windows目录下.这些XML文件分别定义了同特定软件相关的版本策略以及系统范围内的版本控制策略.
命名
你可以随意命名私有的assembly,只要其名称在应用程序内唯一即可.另一方面,公共assembly则需要采用某种全局唯一标识符以便.NET运行时可以识别它们.COM的Class ID和Prog ID已经随风而逝了.现在的共享assembly采用了所谓的strong name命名机制.Strong name来源于标准的公钥加密算法.开发人员用一个私钥"签署"assembly同时提供一个公钥供客户assembly使用.公钥随后成为assembly的strong name的一部分.
采用命令行编译器签署assembly需要使用一些命令行指令选项,因此这也是一项比较繁重的任务.幸好,Visual Studio.NET可以自动地为程序员完成这些工作.
小小装配做大事
微软最后还是承认了DLL地狱问题的存在,而且意识到这一问题只能通过操作系统级施加控制策略才能得以弥补.在注册表和对COM应用程序单个组件支持这方面瞎折腾一气之后,看起来好象微软已经走上了正途.事实上,有了assembly机制,安装.NET应用程序完全可能变成使用Xcopy命令拷贝程序那么简单!
SN.EXE工具
强名称工具有助于使用强名称对程序集进行签名.Sn.exe 提供用于密钥管理、签名生成和签名验证的选项.
VS2005 strong name 使用例子
先利用SN.exe这个工具生成一个密匙文件SampleKey.snk,这个文件的英文原文叫string name key file,然后用加密的算法根据SampleKey.snk生成一个SampleKeyPublic.snk.最后在根据SampleKeyPublic.snk提取一个public key token ,public key token是一个16位的数字和字母混合的数:大致流程如下:
SampleKey.snk --根据一定的算法--> SampleKeyPublic.snk---->public key token 所以我们只要SampleKey.snk和public key token就可以了,SampleKeyPublic.snk就没什么用了.因为SampleKeyPublic.snk的贡献做完了.
实际操作如下:
1.打开SDK Command Prompt或者VS2005中的Visual Studio 2005 Command Prompt.而不是windows的cmd
2.输入sn -k SampleKey.snk,得到的文件在命令提示符的当前文件夹下(微软叫文件夹很少叫目录,最正点是folder)
3.输入sn -p SampleKey.snk SampleKeyPublic.snk (从SampleKey.snk中提取公匙存入SampleKeyPublic.snk文件)
4.输入sn -t SampleKeyPublic.snk 得到public key token
打开VS2005,找到项目,然后右击"项目名"找到"属性","属性"里面有个"Signing"的选项卡,然后钩上 "Sign the assembly",再Choose a strong name key file.做完了操作,然后记得保存,编译 这样你的DLL才能拖到GAC,GAC就是"全局程序集缓存",这就是为什么你的你的项目的bin文件夹下没有System.Data,你都能引用的原因,因为程序会自动去找GAC,GAC的位置在win 2003中是"c:\windows\assembly".