创建强命名程序集

如何部署强命名程序集(Strong Name Assembly)和GAC

如何创建强命名程序集(Strong Name Assembly)
 
   创建一个强命名程序集首先需要获得一个用强命名实用工具
   (Strong Name Utility,即SN.exe,.NET SDK自带)产生的密钥。
   下面简要介绍一下SN.exe的一些用法。 要产生一个公钥/私钥对:
 
   a)SN –k MyCompany.Keys
   该命名告诉SN.exe创建一个名为MyCompany.keys的文件。MyCompany.keys文件将包含以对以二进制格式存储的公有密钥和私有密钥。
 
   b)查看公有密钥:
   首先生成一个只包含公有密钥的文件: SN –p
   MyCompany.keys MyCompany.PublicKey
   然后用-tp参数查看:SN –tp MyCompany.PublicKeys
   Public key is
 
   00240000048000009400000006020000002400005253413
 
   10004000001000100bb7214723ffc13901343df4b9c464ebf
 
   7ef4312b0ae4d31db04a99673e8163768cc0a2a7062e731d
 
   beb83b869f0509bf8009e90db5c8728e840e782d2cf928dae
 
   35c2578ec55f0d11665a30b37f8636c08789976d8ee9fe9a5
 
   c4a0435f0821738e51d6bdd6e6711a5acb620018658cce93
 
   df37d7e85f9a0104a5845053995ce8
 
   Public key token is 2dc940d5439468c2
 
   创建好了公钥/私钥对,创建强命名程序集就很容易了。只需要把System.Reflection.AssemblyKeyFileAttribute特性加入到源代码中就可以了:?[assembly:AssemblyKeyFile("MyCompany.keys")]
 
   说明:公钥/私钥对文件的扩展名可以是任意的(也可以没有),因为编译的时候都是以元数据的格式读取的。
 
   4.程序集的部署方式
   一个程序集有两种部署方式:
   a)私有方式
   和应用程序部署在同一目录下的程序集称作私有部署程序集。弱命名程序集只能进行私有部署。
 
   b)全局方式
   全局部署方式将程序集部署在一些CLR已确知的地方,当CLR搜索程序集时,它会知道到这些地方去找。强命名程序集既可以进行私有部署,也可以进行全局部署。
 
    5.如何部署强命名程序集(Strong Name Assembly)和GAC
   a)GAC的概念
   如果一个Assembly要被多个应用程序访问,那么他就必须放在一个CLR已确知的目录下,并且CLR在探测到有对该Assembly的引用时,它必须能自动到该目录下寻找这个程序集。这个已确知的目录称作GAC(Global Assembly Cache),就是全局程序集缓存。它一般位于下面的目录下:<System Drive>:"Windows"Assembly"GAC。
   GAC的作用就是提供给CLR一个已知的确定的目录去寻找引用的 程序集。
 
   b)GAC的内部结构
   GAC是一个特殊的结构化的目录,用Windows Explorer浏览你会以为它只是一个包含很多程序集的普通目录。其实不是这样的,在命令行下查看,你会发现它实际上包含很多子目录,子目录的名字和程序集的名称是相同的,但它们都不是实际的程序集,实际的程序集位于程序集名对应的目录下。比如进入GCFWK子目录,我们会发现其中又有很多的子目录。机器内每一个安装到GAC的GCFWK.dll在GCFWK中都会有一个子目录。


这里只 有一个目录表明只有一个版本的GCFWK程序集被安装。实际的程序集保存在每一个对应的版本目录下。目录的名称以下划线的形式分割为“(Version)_(Culture)_(PublicKeyToken)”。
 
   GCFWK的语言文化信息为netture,就表示为0.0.0__bf5779af662fc055”。 表示得意义是: “GCFWK, Version=1.0.0.0, Culture=neutral,PublicKeyToken=bf5779af662fc055” 如果语言文化信息为”ja”,就表示”1.0.0.0_ja_bf5779af662fc055”
 
   表示得意义是: “GCFWK, Version=1.0.0.0, Culture=ja, PublicKeyToken=bf5779af662fc055”
 
   c)部署强命名程序集到GAC
 
   GAC包含很多子目录,这些子目录是用一种算法来产生的,我们最好不要手动将程序集拷贝到GAC中,相反,我们应使用工具来完成这样的工作。因为这些工具知道GAC的内部结构J
 
   在开发和测试中,最常用的工具就是GACUtil.exe。 在GAC中注册程序集跟COM注册差不多,但相对更容易:
   1.把程序集添加到GAC中: GACUtil /i sample.dll (参数/i是安装的意思)
   2.把程序集移出GAC GACUtil /u sample.dll (参数/u就移除的意思)
   注意:不能将一个弱命名程序集安装到GAC中。
   如果你试图把弱命名程序集加入到GAC中,会收到错误信息:”
   Failure adding assembly to the cache: Attempt to install an assembly without a strong name”
   d)强命名程序集的私有部署
 
   把程序集安装到GAC有几个好处。首先,GAC使得很多程序可以共享程序集,这从整体上减少了使用的物理内存;其次,我们很容易将一个新版的程序集部署到 GAC中,并通过一种发布者策略(差不多就是一种重定向方法,比如将原来引用版本为1.0.0.0程序集的程序,通过更改它的配置文件,转而让程序去引用版本为2.0.0.0的程序集)来使用新版本;最后,GAC还提供了对不同版本程序集的并存(side-by-side)管理方式。但是,GAC的安全策略通常只允许管理员更改,同时,向GAC中安装程序集也破坏了.NET框架的简单拷贝部署的许诺。
 
   除了向GAC或者以私有部署方式部署强命名程序集之外,我们还可以将强命名程序集部署在仅为一小部分程序知道的某个任意目录下。配置每一个应用程序的 XML配置文件,让它们指向一个公有目录,这样,在运行时,CLR将知道到哪里去找这个强命名程序集。但这样又有可能会引发”DLL Hell”的问题,因为没有哪个程序可以控制这个程序集何时被卸载。这在.NET中也是不被鼓励的。
强命名策略:

生成公钥与私钥对,并对私钥做严格的保护
生成:sn -k keyfile.snk 公钥与私钥对
抽取公钥:sn -p keyfile.snk public.snk 从keyfile中抽取公钥保存到public.snk文件中,以对程序集进行迟签名
跳过验证:sn -Vr assembly 对assembly在开发用机上进行跳过验证处理,该assembly不是已签名的
签名:sn -r assembly keyfile.snk 对assembly 进行迟签名,这一步是在发布之前做
取消跳过验证:sn -Vu assembly 对assembly在开发用机上取消跳过验证,该assembly这时是已签名的
或取消所有:sn -Vx 取消所有验证

开发阶段
assembly不是已签名的,但是强命名的strong named,因此需要在开发机上做跳过验证处理

发布阶段
由私钥控制者对assembly进行签名,并在开发机上由开发人员自行取消跳过验证


引用的程序集没有强名称的解决办法
我在PetShop4程序中加入了一个业务外观层,然后在业务逻辑层(PetShop.BLL)引用这个程序集,点“生成”,出现以下的错误:“程序集生成失败 -- 引用的程序集没有强名称”,原因是PetShop.BLL是强命名程序集,强命名程序集不能用普通程序集造成的。

        那么什么叫强命名程序集呢?我们知道,以前在Windows下开发程序时常会遭遇著名的“DLL Hell”问题,即动态链接库的向后兼容问题。微软在. Net产生前曾尝试使用COM组件的方式来解决DLL Hell问题,即使用Guid来唯一的标识每一个COM组件。但是,实际上使用COM组件(包括版本升级)也是一件颇为麻烦的事:为了运行COM组件就必须在组册表中对其进行注册,重新编译有可能破坏Guid从而导致原来引用此COM组件的程序不能正确运行,等等。

在.Net中,微软引入了一种新的解决方案:强命名程序集(Strong Name),以及与之配套的全局程序集缓存(GAC)来解决这个问题。

我们知道,.Net使用Name、Version、Culture、PublicToken四个属性来唯一标识一个程序集,而不同产品前三个属性(Name、Version和Culture)完全相同的情况是有可能发生的,如此一来,这唯一标识程序集可重任就落到PublicToken的头上了。强命名的程序集正是使用RSA来保证PublicToken的唯一性,因为在理论上,非对称算法RSA生成的公钥/私钥对不会重复。.Net正是通过在编译项目时将指定的公钥/私钥对写入程序集来保证其唯一性。

对于全局程序集缓存(GAC),MSDN是这样介绍的:安装有公共语言运行库的每台计算机都具有称为全局程序集缓存的计算机范围内的代码缓存。全局程序集缓存中存储了专门指定给由计算机中若干应用程序共享的程序集。

在开发一般的、非共享的程序时,我们不需要使用强命名的程序集,仅将项目(Project)编辑成.DLL或者.EXE即可。但是,如果我们开发的是组件库、框架时,通过对程序集进行强命名,并使用将其部署到GAC中,可以保证我们的程序集不会出现版本问题。

那么,如何创建强命名的程序集呢?以下是其步骤

使用SN工具来生成密钥对。该工具位于安装.NET Framework SDK的Bin目录中,在命令行中使用“ SN -k [驱动器号]:[放置密钥的目录][密钥名称].snk ”这样的语句可以生成密钥对。如,我们使用 SN -k C:"MySloutionKey.snk,可以把名为MySloutionKey.snk的密钥对文件生成到C盘根目录下;
此时,该密钥对并未与项目的程序集建立关联,我们需要打开项目(Project)的AssemblyInfo.cs 文件。此文件具有一个程序集属性列表,默认情况下,在 Visual Studio .NET 中创建项目时将包括这些属性。在代码中修改名为“AssemblyKeyFile”的属性,如下所示:
[assembly:AssemblyKeyFile("C:"MySloutionKey.snk")]

这样,编译该项目即生成强命名的程序集。
         根据以上的说法,这个错误的解决问题如下:

首先打开visual studio 2005命令提示(开始-->程序-->microsoft visual studio 2005-->visual studio  tools-->visual studio 2005命令提示),在其中输入:sn  -k  PetShop.IBLL.snk回车,这样就生成了 PetShop.IBLL.snk,在路径C:"Program Files"Microsoft Visual Studio 8"VC找到 PetShop.IBLL.snk文件,放在IBLL项目的根目录也就是IBLL目录下,然后打开BLL项目的AssemblyInfo.cs,在里面加入如下代码行:[assembly: AssemblyKeyFile("PetSHop.IBLL.snk")],然后重新生成PetShop.IBLL项目,这样一个强命名的程序集就生成了。

posted on 2009-02-23 01:02  hdbb30  阅读(1500)  评论(0编辑  收藏  举报

导航