我如何解决Nuget DLL地狱-无论我做什么VS都坚持认为dll版本与软件包中的版本不同

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我如何解决Nuget DLL地狱-无论我做什么VS都坚持认为dll版本与软件包中的版本不同相关的知识,希望对你有一定的参考价值。

在更新Nuget之后,我与DLL的地狱一直挣扎了一个多星期。我设法通过手动编辑解决方案,项目和包文件解决了大多数问题。但是,无论我做什么VS都坚持认为dll版本与Nuget安装的版本不同。有问题的库是MailKit,在更新之前可以正常使用。现在安装的版本是2.4.1,但是尽管显示了正确的位置,属性网格仍坚持使用版本2.4.0:

Property grid showing the incorrect version being displayed

我尝试了以下所有方法,但都没有成功:

  • 更新包-重新安装
  • 手动删除Nuget缓存
  • 手动删除计算机上2.4.0 dll的每个副本
  • 在整个代码库中搜索对2.4.0的任何引用,然后手动编辑代码以删除引用或重新编号为正确的版本
  • 从命令行删除Nuget缓存
  • 我可以在StackOverflow上找到的所有其他建议解决方案

无论我做什么,它仍然显示错误的版本,因此在应用程序运行时会抛出异常,因为正确的版本是在本地复制的。

谁能建议我如何解决这个问题?

编辑:

Package Config:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="BouncyCastle" version="1.8.5" targetFramework="net452" />
  <package id="JetBrains.Annotations" version="2019.1.3" targetFramework="net452" />
  <package id="MailKit" version="2.4.1" targetFramework="net452" />
  <package id="MimeKit" version="2.4.1" targetFramework="net452" />
</packages>

项目文件(仅引用MailKit和MimeKit,其余部分删除为不必要的内容,如果需要更多内容,请通知我:]

<Reference Include="MailKit, Version=2.4.1, Culture=neutral, PublicKeyToken=4e064fe7c44a8f1b, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..packagesMailKit.2.4.1lib
et45MailKit.dll</HintPath>
</Reference>
<Reference Include="MethodExtensions, Version=1.0.4469.11621, Culture=neutral, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>....LibrariesMethodExtensionsinDebugMethodExtensions.dll</HintPath>
</Reference>
<Reference Include="MimeKit, Version=2.4.1, Culture=neutral, PublicKeyToken=bede1c8a46c66814, processorArchitecture=MSIL">
  <SpecificVersion>False</SpecificVersion>
  <HintPath>..packagesMimeKit.2.4.1lib
et45MimeKit.dll</HintPath>
</Reference>

进一步编辑:

为澄清起见,软件包安装的dll版本显然是2.4.1:

Properties of the referenced DLL

这里是运行时错误消息,确认它正在寻找2.4.0,在更新Nuget之后,它不再在计算机上:

Runtime error message

解决方案

@ zivkan的回答向我指出了正确的方向。首先,我一直在寻找完全错误的东西,假设“属性网格”中的版本不正确,而实际上它是完全正确的。该引用位于一个插件模块中,该模块本身会编译为一个库,这意味着在编译MailKit dll时,不仅必须将其复制到本地,还必须使用构建后事件命令行将其复制到主应用程序文件夹中。事实证明,构建后事件代码中存在错误,因此没有复制MailKit,而MimeKit被复制了两次。不为那个人负责,但我为没有意识到问题而负责!

谢谢@zirkan,您的帮助和解释最终使我达到了解决方案...

答案

应用运行时,由于正确的版本是本地复制的,因此会引发异常。

您是说不正确?我不明白如果复制正确的版本,为什么会引发异常。无论如何,如果您向我们展示实际的错误,将会更有帮助。我将用这个答案的其余部分来解释为什么其他所有内容都按设计工作,这意味着您没有给我们足够的信息来理解您的问题,因此很难提出一个好的解决方案。

无论如何,NuGet包只是一个zip文件(重命名为.nupkg),其中包含一些文件,通常是一些.NET程序集。因此,放弃基本的问题,如果程序包中的不同程序集具有不同的版本会发生什么呢?答案是什么,因为程序集版本和程序包版本是独立的。通常它们是相似的,或者(几乎)完全相同,但是由于它们是独立的,因此没有理由它们不会有所不同。

程序集也有多个版本。首先,如果在Windows资源管理器中找到.dll,请右键单击,选择属性,然后转到“详细信息”选项卡,您将看到所有(或大多数)dll具有产品版本和文件版本。这并非特定于.NET,所有Windows可执行文件均具有此元数据。如果使用ILSpy或类似方法检查.NET程序集,则会看到存在AssemblyFileVersion,AssemblyInformationalVersion和AssemblyVersion属性。因此,总共至少有5个不同的版本元数据,它们都是独立的,因此可以不同。那是在我们认为NuGet软件包版本是第6个独立版本号之前。

现在,属性窗口中的程序集对NuGet一无所知。它向您显示文件的路径,由于NuGet将软件包提取到包含软件包版本的路径,因此我们可以在路径中看到它。但是在属性窗口中显示的版本是程序集版本。因此,在这种情况下,MailKit v2.4.1程序包包含程序集版本为2.4.0.0的MailKit.dll。 Visual Studio的属性窗口向您显示正确的信息,没有问题。

我的回答已经足够长了,所以我不会赘述很多,但是软件包作者可以选择在其软件包的多个版本中使用相同的程序集版本,以最大程度地减少需要绑定重定向的次数。但是,这仅在不同产品版本兼容时才有效。当它们不兼容并且两个不同的程序集都依赖于相同的程序集版本的依赖关系时,就不可能同时加载两个不同的版本以解决此问题(是的,当同一个程序集具有不同的程序集版本时,则可以同时加载两个文件,这需要额外的工作)。

以上是关于我如何解决Nuget DLL地狱-无论我做什么VS都坚持认为dll版本与软件包中的版本不同的主要内容,如果未能解决你的问题,请参考以下文章

vs 如何将dll打包到exe中

DLL上传私有Nuget服务器并配置 VS 中Nuget源

VS NuGet加载本地程序包

NuGet 包还原 + NuGet 源设置

VS2010 .net网站怎么重新生成bin下 工程名.dll文件

从 NuGet 安装 NUnit 后,如何强制 TestDriven.Net 使用 NuGet 引用的 NUnit dll?