确定间接依赖项来源于错误的.NET Framework版本

19

我想知道如何确定这个构建错误的来源;

Warning 4   The primary reference "MyNamespace.MyProject" could not be resolved because 
   it has an indirect dependency on the .NET Framework assembly "System.Xml, Version=4.0.0.0,
   Culture=neutral, PublicKeyToken=b77a5c561934e089" which has a higher version "4.0.0.0" than
   the version "2.0.0.0" in the current target framework.   MyNamespace.MyOtherProject
我理解这个错误的意思(和这个项目中其他5个类似的错误),但是我无法确定如何在我的情况下解决它。在这种情况下,“主要参考”(MyNamespace.MyProject)没有直接依赖于.NET 4.0.x。
主要引用仅依赖于我的另一个项目(MyNamespace.MyCoreProject),而该构建的源项目(MyNamespace.MyOtherProject)也直接依赖于其上。构建没有抱怨关于那个项目对.NET 4.0.x的间接引用,所以我认为我可以排除那个。
主要参考有三个(3)第三方DLL的直接依赖项,所有这些都指向.NET 2.0。
我使用dotPeek检查了生成的库,看不到任何引用使用.NET 4.0。唯一可能存在问题的是PostSharp的使用,它是由“ MyNamespace.MyCoreProject”(被主要引用项目引用)直接引用的,这可能会导致问题,因为在引用PostSharp.dll时我相信与VS2010有关的错误(http://www.sharpcrafters.com/forum/Topic4444-4-1.aspx#bm4462),然而我还从生成链中删除了它,仍然看到此错误,所以我认为我也可以排除那个。
如果有人能告诉我为什么会发生这种情况,那太好了!如果没有,对于如何找出未命名的“间接引用”的方向将同样有帮助!
顺便说一下,我尝试了以下所有工具以获取一些信息,但它们并没有告诉我太多我不知道的内容(即DLL的直接依赖项); - .NET Reflector - dotPeek - IldAsm - Depends(Dependency Walker)

仅仅因为它没有引用任何4.0代码,不意味着它在运行时不需要4.0二进制文件。 - Cole Tobin
如果没有任何东西依赖于4.0框架,那么我就不需要4.0框架。我正在尝试找出是什么需要4.0框架。 - RJ Lohan
你已经打开项目属性并更改依赖框架了吗? - Cole Tobin
看起来你有一个针对 .net2 构建的项目,引用了一些 v4 程序集。检查每个引用的属性,其中一个或多个将是 v4。移除并替换为 .net 2 版本。 - Tony Hopkinson
@ColeJohnson 我的代码中所有内容都针对3.5(即.NET 2.0 CLR)。 - RJ Lohan
@TonyHopkinson,没错,这就是错误信息所说的。但是我找不到使用System.Xml v4.0.0.0的东西 - 这就是问题的关键所在。 - RJ Lohan
8个回答

7
虽然我还没有想出一个好方法来解决确定MsBuild如何确定它使用的引用的问题(为什么它不告诉我它是如何得出这些间接引用的,而是让我猜测,我不知道...),但是我已经解决了我的问题。
最终,我基本上删除了“主要引用”项目中的所有引用(这需要逐个排除所有代码 - 一种有点痛苦的过程),以确定所谓的间接引用到.NET 4.0库的源头是由被引用的第三方DLL引起的。
然而,我确实相信在这个问题背后有一个MsBuild的错误,因为:
1. 第三方DLL是通过“浏览”到我的计算机上的特定DLL文件进行引用的 - 这个文件非常明确地只依赖于.NET 2.0。 2. 在构建中将“特定版本”设置为true并没有解决这个问题。 3. MsBuild似乎正在前往GAC获取这个DLL的一个不同版本,从而导致错误的引用。
现在,另一个奇怪的事情是,我已经有一段时间没有触及或更改相关的库,所以这个问题只是因为某些与之无关的原因而开始发生 - 我不知道那是什么。
最后,我找到的唯一解决这个问题的方法是对每个相关库运行gacutil /u,以删除先前安装/使用的4.0库版本(包中有大约40个,所以这也很痛苦!因为包的卸载程序没有删除GAC中的库)。
这似乎让msbuild开始使用我告诉它的引用,而不是想出自己的“使用这个文件”和“使用这个特定版本”的想法。
问题已解决,但我希望有一种更简洁的方法来解决这个问题!

1
你如何使用gacutil解决它?这需要在命令提示符中提供一个参数。 - Aryo
“程序集显示名称”究竟是什么?整个过程都需要公钥令牌吗? - roberto tomás

2

我曾经遇到过这个问题,使用了CheckAsm工具来确定其中一个我自己的程序集不知何故引用了一个.NET 4.0版本的第三方库,而应用程序本身是.NET 2.0。我从硬盘中删除了所有该程序集的实例(有很多副本),重新构建了解决方案,一切都很好。


2
尝试使用MSIL 反汇编器工具来检查所有可疑的程序集。
  1. 打开 DLL,按下 Ctrl + M 并滚动到屏幕底部。您可能会看到对一些 .NET 4 程序集的引用,像这样:

程序集引用 #1 (23000001)

Token: 0x23000001
Public Key or Token: b7 7a 5c 56 19 34 e0 89 
Name: mscorlib
Version: 4.0.0.0
Major Version: 0x00000004
Minor Version: 0x00000000
Build Number: 0x00000000
Revision Number: 0x00000000
Locale: <null>
HashValue Blob:
Flags: [none] (00000000)
  1. 查找从该.NET程序集中加载的类型,使用ref#作为搜索条件。以下是您可以在屏幕上找到的类型示例:

    TypeRef #18 (01000012)

    标记:0x01000012 解析范围:0x23000001 TypeRef名称:System.Runtime.CompilerServices.CompilationRelaxationsAttribute

  2. 调查为什么使用该类型。

更新: 您是否尝试将MSBuild项目生成输出详细程度设置为“详细”(Tools\Options\Projects and Solutions\Build And Run页面),然后重新构建解决方案?您可能会在ResolveAssemblyReference目标中看到一些内容。


谢谢,我已经看过了,但它并没有告诉我比其他几个工具更多的信息;它让我看到了直接依赖项(其中没有一个是针对4.0的),但仅限于此。实际上,它似乎也没有告诉我特定程序集所针对的框架是哪个。你指出的版本只是程序集版本,这并不一定与它所需的.NET框架相关。 - RJ Lohan
你尝试过在“工具\选项\项目和解决方案\生成和运行”页面上将MSBuild项目构建输出详细程度设置为“详细”,然后重新构建解决方案吗?你可能会在ResolveAssemblyReference目标中看到一些东西。 - Dmitry Harnitski
是的,我正在处理这个问题,但它并没有给我太多线索,而且日志文件非常长(650万行!) - RJ Lohan
应该有一些关于 .net 4.0 dll 的参考。它可能非常间接,但它应该存在。尝试查找子字符串 "System.Xml, Version=4.0.0.0" 并跟随路径。 - Dmitry Harnitski
日志中没有这样的字符串(除了报告错误),这就是问题的一半。那个文件没有被我的任何代码引用,实际上也没有被我的代码引用的任何引用所引用!请参见下面的答案以获取我的“解决方案”。 - RJ Lohan

2

在我的情况下,程序集已被卸载并且所有引用(据我所知)都已被删除。

在 app.config 中找到它:

<runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            ...
        </dependentAssembly>
    </assemblyBinding>
</runtime>     

删除了dependentAssembly,我的应用程序又可以正常工作了。


一直以来都是app.config的问题。我已经删除了所有与库相关的引用和链接,但构建仍然会抱怨找不到库……而我已经从系统中清除了它,完全没有必要。我甚至尝试强制所有项目使用一个明确的较低版本,但仍然失败。项目文件很干净,没有痕迹……除了app.config。不知道为什么,但app.config决定需要使用这个库。如果诊断构建日志告诉我原因,那就太好了。 - Ryan Beesley

1
我可以帮您翻译成中文:我也遇到了这个问题,event.er 带领我找到了解决方案。我在我的 app.config 中有以下内容:
  <dependentAssembly>
    <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-2.0.0.0" newVersion="4.0.0.0" />
  </dependentAssembly>

我把newVersion改为"2.0.0.0",然后解决方案就编译成功了。


0

我的猜测是第三方DLL没有为其依赖项设置特定版本,这可能导致了你的问题。


0

在一个针对.NET 4.5的项目中,我遇到了System.Data.SQLite.dll的问题,后来发现安装了一个针对4.5.1版本的GAC_32。

如果我使用Copy Local = True来构建解决方案,就没问题了。但是因为我要将SQLite程序集嵌入最终构建中,所以这似乎是不必要的,我想把它解决掉。

我尝试运行gacutil -u System.Data.SQLite.dll,但遇到了一些问题,最后我只是使用了Windows的程序和功能进行卸载,然后一切都好了。


0
如果使用Visual Studio 2019并且正在尝试构建.NET 3.5项目,则可以采用以下方法:
Visual Studio服务包和新的Visual Studio 2019将程序(通常是WebDeploy)放置在Program Files中,并将此文件夹置于计算机的程序集探测路径的高处(因此,net45 JSON.NET程序集会在任何其他程序集之前被拾起)。
要找出从哪里解析您的程序集,请使用SysInternals Process Monitor并过滤引用的DLL。然后启动构建。Process Monitor会告诉您它正在从哪里解析该程序集,通常是安装了VS2019的WebDeploy文件夹中的一个程序集。如果您不使用WebDeploy工具,则可以清除该文件夹。
具体来说,在我的情况下,我删除了 C:\Program Files\IIS\Microsoft Web Deploy V3\Newtonsoft.Json.dll 文件,然后我的构建就成功了。

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