为了账号安全,请及时绑定邮箱和手机立即绑定

Nuget DLL Hell:无法加载文件或程序集System.Runtime

Nuget DLL Hell:无法加载文件或程序集System.Runtime

C#
莫回无 2023-07-22 16:00:06
今天将 Application Insights 升级到最新版本后,由于我们的站点不再报告调用堆栈,我们的 .NET Framework 4.6.1 ASP.NET 站点现在在初始化时崩溃,原因如下:System.IO.FileLoadException: 'Could not load file or assembly 'System.Runtime, Version=4.2.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)'我过去在另一份工作中也曾遇到过类似的问题。关键区别在于该问题是由引入 .NET Core 或 Standard 的 Nuget 包引起的。因此,多个同名的 .NET DLL 被复制到 bin 文件夹(在这种情况下为 System.Net.Http)。在这种情况下,就像不再更新 Nuget 包一样“简单”......尽管我认为这里的情况略有不同,但“不升级”不再是一个选择。Application Insights 不再报告调用堆栈有点违背了整个事情的目的!由于它是 System.Runtime,而不是 Nuget 包,因此配置文件中没有用于 nuke 的依赖版本标记;尽管这样也行得通,但无论如何,这似乎只是一个临时解决方案。我推测现在项目中的某个地方可能隐藏着 .NET Core 的 .NET 标准,但我没有看到 NetStandard 参考,而且我不知道如何判断 Core 是否被以某种方式拖入。我还没有愉快地(?)使用标准版或核心版,还没有立即了解更多信息。我会继续谷歌搜索...我认为这是因为我们有一个 .NET 3.5 DLL(除了普通的 .NET Framework 3.5 的 System、System.Runtime.Serialization 和 System.Xml 之外,Nuget 或 DLL 引用为零),被 ASP.NET 项目引用,尽管这以前从未出现过问题。我完全被难住了,并停止了当天的所有开发。我一直在升级和降级各种软件包,查看它们的先决条件,但我没有找到任何提示。
查看完整描述

1 回答

?
慕无忌1623718

TA贡献1744条经验 获得超4个赞

两个不同的 Nuget 想要引入不同版本的 System.Runtime.dll。这在使用使用 .NET Standard 的 Nuget 的 .NET 项目中极为常见。这是我第二次遇到源自 System.Net.Http 的问题,因为几乎每个人都使用它。

Program Files\Reference Assemblies由于 System.Runtime 是一个 .NET Framework DLL,因此无论您在 Visual Studio 或 CSProj 中执行什么操作, Visual Studio 都会始终从该文件夹中获取它。

就我而言,无论出于何种原因,复制到 bin 文件夹的版本是所需 DLL 的仅反射版本,这意味着我不能简单地使用标签来强制它使用<dependantAssembly>bin 文件夹中的版本。我必须首先将完整版本的 System.Runtime.dll 放入 bin 文件夹中。

除了更新到 .NET Core 之外,我唯一的想法(并得到另一位 Stack Overflow 用户的证实)是在构建后手动复制它。这很糟糕,但它可以与您拥有的任何冲突的 DLL 一起使用:

  1. 由于 Nuget 包的原因,您的项目引用中可能会存在冲突的 DLL。我的问题更困难,因为虽然 System.Runtime 是我使用的另一个 Nuget 的先决条件,但我想因为它是 .NET Framework 的一部分,所以它没有作为 Nuget 包或引用添加。如果没有,就自己去拉Nuget包。

  2. 在包文件夹中查找 DLL 的路径。例如,我的是$(SolutionDir)packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll. 您将需要$(SolutionDir)像我一样将解决方案目录与宏交换。

  3. 在项目的解决方案属性中编辑构建后事件命令行:

    copy "$(SolutionDir)packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll" "$(TargetDir)System.Runtime.dll"

  4. 在可以看到其版本号和公钥令牌的工具中打开 DLL,例如 ILSpy。就我而言,DLL 的版本为 4.1.1.1,公钥标记为 b03f5f7f11d50a3a。请注意,在文件资源管理器中查看 DLL 的属性不会显示正确的版本号。

  5. 在文本编辑器中打开 app.config/web.config。如果标签中还没有<dependentAssembly>DLL 的标签configuration\runtime\assemblyBinding,请添加它。它应该看起来像这样:

<dependentAssembly>    <assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>    <bindingRedirect oldVersion="0.0.0.0-9.9.9.9" newVersion="4.1.1.1"/> </dependentAssembly>

  1. (续)将该名称替换为不带 .DLL 扩展名的 DLL 文件名。将公钥标记替换为您在 ILSpy 中发现的值。将 oldVersion 设置为较宽的范围。将 newVersion 设置为您在 ILSpy 中找到的版本。

  2. 每当您在 Nuget 包管理器中触摸该 nuget 包时,它可能会更改您的<dependentAssembly>标签!因此,在你的项目上留下一个文本文件、一张便利贴、一个霓虹灯标志,说明如果你弄乱了那个 Nuget 包,你可能需要编辑构建后和 app.config/web.config。

  3. 哭。

如果您像我一样被困在 .NET Framework 上,您可能最终不得不对许多 DLL 进行这种修改,因为 .NET Standard/Core 变得更加普遍,因此更多的 DLL 最终与它们的 .NET Framework 对应项具有相同的名称。我们发现将此解决方案部署到 Azure 上不起作用。

否则,唯一的其他解决方案是完全避免它:一次仅升级一个 Nuget 包,并在每次之后进行彻底测试。Nuget 可以像俄罗斯轮盘赌;-)。尽管上述方法对我们有用,但我们最终还是回滚并缓慢而痛苦地升级,直到找到罪魁祸首。

如果您知道更好的方法,我很想听听。


查看完整回答
反对 回复 2023-07-22
  • 1 回答
  • 0 关注
  • 235 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信