BLOG zzy.my

合抱之木, 生于毫末; 九层之台, 起于累土; 千里之行, 始于足下。

Assembly generation failed -- 程序集生成失败 -- 引用的程序集没有强名称

什么叫强命名程序集?
我们知道,以前在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 命令提示(开始-->程序-->microsoft visual studio-->visual studio tools-->visual studio 命令提示),在其中输入:sn -k XXX.snk回车,这样就生成了 XXX.snk,在路径C:\Program Files\Microsoft Visual Studio X\VC找到 XXX.snk文件,放在项目的根目录下,然后打开项目的AssemblyInfo.cs,在里面加 入如下代码行:[assembly: AssemblyKeyFile("XXX.snk")], 然后重新生成项目,这样一个强命名的程序集就生成了


-------------------------------------------------------------------

为没有源码的DLL文件添加强名称

如果项目中引用了其他没有源码的dll文件,并且此dll文件是没有强名称的程序集,则编译时会出现类似 "Assembly generation failed -- 引用的程序集 'xxxxxxxxxxx' 没有强名称" 这样的错误。
我这里引用的是Interop.Scripting.dll程序集,它不是强名称的,则需要进行以下操作:
1.打开SDK 命令提示窗口;
2.创建一个新的随机密钥对:
sn -k Interop.Scripting.snk
3.反编译目标程序集

ildasm Interop.Scripting.dll /out=Interop.Scripting.il
3.重新编译,附带强命名参数

ilasm Interop.Scripting.il /dll /resource=Interop.Scripting.res /key=Interop.Scripting.snk /optimize
4.验证签名信息
sn -v Interop.Scripting.dll


OK,将生成的dll文件重新引入到项目中然后编译。

Loading