如何修复“引用的程序集没有强名称”错误

276

我已将一个弱名称程序集添加到我的Visual Studio 2005项目中(该项目是强名称的)。 现在出现以下错误:

"引用的程序集 'xxxxxxxx' 没有强名称"

我需要对这个第三方程序集签名吗?


1
https://dev59.com/R3M_5IYBdhLWcg3wzmkw - user423430
2
这可能听起来像一个愚蠢的提示,但如果你发现无论你做什么都无法签名汇编,那就检查一下你的构建设置;记住,当你重新构建/清理时,VS不会清除其他架构(任何CPU、x64等),因此你可能正在查看来自另一个架构的过时dll。 - jrh
@jrh 我的构建一直告诉我我的项目没有强名称,但是我已经签名了!我甚至安装了StrongNamer nuget包,但它仍然抱怨程序集未签名。说实话,这种故障排除是最不愉快的事情之一。 - Vin Shahrdar
16个回答

236
为了避免这个错误,您可以:
  • 动态加载程序集;或者
  • 对第三方程序集进行签名。

有关签署第三方程序集的说明,请参见 .NET-fu:签署未签名程序集(无延迟签名)

签署第三方程序集

签署第三方程序集的基本原则是

  1. Disassemble the assembly using ildasm.exe and save the intermediate language (IL):

    ildasm /all /out=thirdPartyLib.il thirdPartyLib.dll 
    
  2. Rebuild and sign the assembly:

    ilasm /dll /key=myKey.snk thirdPartyLib.il
    

修复附加引用

以上步骤适用于没有附加引用的第三方程序集(A.dll),但如果该程序集引用了另一个库(B.dll)并且该库也需要签名,则上述步骤将无法正常工作。您可以使用上述命令对 A.dllB.dll 进行反汇编、重建和签名,但在运行时,加载 B.dll 将失败,因为 A.dll 最初是使用对 B.dll 的未签名引用构建的。

解决此问题的方法是修补步骤 1 中生成的 IL 文件。您需要将 B.dll 的公钥标记添加到引用中。您可以通过调用以下命令来获取此标记:

sn -Tp B.dll 

这将为您提供以下输出:

Microsoft (R) .NET Framework Strong Name Utility  Version 4.0.30319.33440
Copyright (c) Microsoft Corporation.  All rights reserved.

Public key (hash algorithm: sha1):
002400000480000094000000060200000024000052534131000400000100010093d86f6656eed3
b62780466e6ba30fd15d69a3918e4bbd75d3e9ca8baa5641955c86251ce1e5a83857c7f49288eb
4a0093b20aa9c7faae5184770108d9515905ddd82222514921fa81fff2ea565ae0e98cf66d3758
cb8b22c8efd729821518a76427b7ca1c979caa2d78404da3d44592badc194d05bfdd29b9b8120c
78effe92

Public key token is a8a7ed7203d87bc9

最后一行包含公钥令牌。然后您需要在A.dll的IL中搜索对B.dll的引用,并按如下方式添加令牌:
.assembly extern /*23000003*/ MyAssemblyName
{
  .publickeytoken = (A8 A7 ED 72 03 D8 7B C9 )                         
  .ver 10:0:0:0
}

2
如果签名程序集是一种选择,我既不希望动态加载程序集,也不希望对其进行签名。我知道强名称是关于全局程序集缓存 (GAC) 的。尽管如此,我不想将我的程序集作为 GAC 的一部分,并且它们也不可见于 COM。我记得有一些东西可以让我们在不签名的情况下使用这个程序集。它可能在选项属性或其他地方。我是否离题了? - Will Marcouiller
31
如果您的程序集也是未签名的,那么可以使用未签名的程序集。 - OJ.
2
.NET-fu的链接是一种非常棒的资源。 - HopAlongPolly
3
虽然上述步骤在“大多数”情况下都有效,但非常耗时、容易出错,并且在处理友元程序集引用等情况下会失败。只需使用此实用程序即可自动完成所有操作(毫不掩饰地推销):https://dev59.com/UnRC5IYBdhLWcg3wVvct#19459609 - BrutalDev
1
如果想要保留文件版本,请在构建动态链接库时添加 /res。ilasm /dll /key=myKey.snk thirdPartyLib.il /res=thirdPartyLib.res - Cyclion
显示剩余3条评论

104

展开使用未“拥有强名称密钥”的项目的项目文件,并查找.snk文件(.StrongNameKey)。

Windows资源管理器中浏览到该文件(以便知道它在哪里)。

回到Visual Studio,在不“拥有强名称密钥”的项目中执行以下操作:

  • 右键单击项目文件
  • 选择属性
  • 选择“签名”选项卡(在左侧)
  • 选中“对程序集进行签名”复选框
  • 然后<Browse>到先前找到的.snk文件

这样就完成了。这为我解决了一个问题,即在同一解决方案中使用另一个项目中的表单时出现的问题。

希望这能帮助你。


如果我不想为我的程序集签名,我一开始就不会签名了! - mohas
如果找不到.snk文件:打开项目属性(使用带有“强名称”错误的项目),选项卡签名。在那里,您将看到用于签署项目的文件(并不总是具有.snk扩展名的文件)。只需将此设置复制到其他项目即可。 - Coder14
正如MrOli3000所指出的那样,它仅在缺少强名称密钥文件的一个解决方案中起作用。如果有多个项目将引用未签名的项目,则最好创建一个新的强名称密钥文件以避免任何冲突。在我的情况下,解决方案无法构建,我一直在尝试修复。从VS2017开始,格式为.pfx而不是.snk,但步骤相同-右键单击解决方案并选择属性。从左侧列出的选项卡中选择“签名”。单击复选框并选择新建...提供一个名称!就这样!完成了! - Raj
.pfx文件的密码是什么?@Raj - samin.hma

70

我也曾遇到同样的问题,将“签署程序集”选项取消勾选对我有用:

图像描述在此输入

(你可能注意到,屏幕截图来自Visual Studio 2010,但希望它能帮助某人。)


我在我的MVC项目中没有检查这个设置。但它仍然抱怨其中一个依赖项。MVC还有其他的设置吗? - Hamid Mayeli

64

我编写了一个工具,用于自动为程序集签名,包括那些你没有源代码或已被弃用的项目。它以一种简单的方式使用许多答案中描述的技术,没有任何现有工具或过时指令的缺陷或不足。

.NET Assembly Strong-Name Signer

我希望这可以帮助需要为第三方程序集签名而无需跳过障碍的人们。


这是一个快速简便的工具。只需添加NuGet引用和预构建命令即可为缺少签名的第三方库进行签名。谢谢! - Frode Evensen
@BrutalDev:这个能用于.NET-Standard-2.0项目和新的项目文件吗?我可以让它在引用未签名程序集的.NET-4.8项目中运行,但不能在.NET-Standard-2.0项目中运行。在我的情况下,我想为Scrypt.NET 1.3.0(Nuget-Package)的DLL添加强名称签名。 - MarkusE
1
@MarkusE 当然,它适用于任何 .NET 程序集。只需将其作为 NuGet 包添加并构建,它应该仍然可以找到您使用的所有未签名引用并签署它们。如果您遇到问题或需要更多帮助,请在 GitHub 问题中发布:https://github.com/brutaldev/StrongNameSigner/issues - BrutalDev

44

如果您的程序集也没有签名,您可以使用未签名的程序集。


35

我签署了第三方程序集,这对我有用:

引用的程序集没有强名称

我学到了如果链接的文章不再有效,发布步骤是很有帮助的。所有功劳归Hiren Khirsaria所有:

  1. 运行Visual Studio命令提示符并进入DLL所在的目录。

    例如,我的DLL位于D:/hiren/Test.dll

  2. 现在使用以下命令创建CIL文件。

    D:/hiren> ildasm /all /out=Test.il Test.dll (此命令生成代码库)

  3. 生成一个新的密钥以签署您的项目。

    D:/hiren> sn -k mykey.snk

  4. 现在使用ilasm命令签署您的库。

    D:/hiren> ilasm /dll /key=mykey.snk Test.il


1
你的链接起了作用!谢谢!它还解释了如何创建mykey.snk文件(其他答案没有说明)。 - Nicolas VERHELST

16

如何给未签名的第三方程序集打上签名

  1. 打开Visual Studio的开发人员命令提示符。该工具可在Windows程序中找到,并可使用默认的Windows搜索进行查找。
  2. 通过执行以下命令确保您的提示符可以访问以下工具:sn ildasmilasm
  3. 转到Cool.Library.dll所在的文件夹
  4. sn -k Cool.Library.snk创建一个新的密钥对
  5. ildasm Cool.Library.dll /out:Cool.Library.il将库反汇编
  6. move Cool.Library.dll Cool.Library.unsigned.dll以备份原始库
  7. ilasm Cool.Library.il /dll /resource=Cool.Library.res /key=Cool.Library.snk使用强名称重新组装库
  8. powershell -command "& {[System.Reflection.AssemblyName]::GetAssemblyName($args).FullName} Cool.Library.dll"获取程序集的完全限定名。 如果您需要在外部配置文件(如web.config或app.config)中引用DLL,则需要此部分。

10

对我而言,问题出在一个没有强名称的 NuGet 包上。解决方法是从 NuGet 安装 StrongNamer,它会自动为所有被引用的程序集添加强名称。只需要在项目中引用它即可修复我的问题。


我发现StrongNamer存在一个问题,重新签名的解决方案似乎没有出现这个问题:在使用库的任何方法中,调试器中的datatips都不起作用。或者至少在我使用此功能的一个项目中,它们没有起作用。我回头做了完整的重新签名(这是个麻烦的事情,因为它是一个可能会在某个时候更新的NuGet项目),现在调试正常工作。 - RobinHood70
1
@RobinHood70 我没有遇到过这个问题,但我使用JetBrains Rider。 - Jan Pokorný
StrongNamer不再支持.NET 4.7及更高版本的框架,它在4.6.1停止工作。 - rboy

7
我在使用通过NuGet安装的ServiceStack DLL文件时遇到了这个问题。结果发现有另一组标记为已签名的DLL文件可用。这不会是每个人的答案,但你可能只需要检查是否存在已签名版本的程序集。

ServiceStack.Signed


6

我曾经遇到这样的问题,一个应用程序被强命名了,但为了引用一个非强命名的程序集,必须更改它,因此我在项目属性签名部分取消了“签名程序集”的勾选,但是仍然出现了错误。我认为这可能是某个地方的残留物导致了问题,因为我已经正确地完成了其他所有步骤。我在其assemblyInfo.cs文件中找到并删除了以下行:[assembly: AssemblyKeyFile("yourkeyfilename.snk")]。之后就没有再出现编译错误。


1
谢谢!由于您的回答,我重新检查了我的问题(ClosedXML),并发现了ClosedXML.Signed NuGet包。 - Kiryl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接