解决MSB3247-发现相同从属程序集的不同版本之间存在冲突


427

使用msbuild进行编译时,.NET 3.5解决方案最终出现此警告。

有时NDepend可能会有所帮助,但在这种情况下,它没有提供任何更多详细信息。像鲍勃一样,我最终不得不诉诸于ILDASM中的每个程序集,直到我找到一个引用较旧版本的从属程序集的程序。

我确实尝试使用VS 2010 Beta 2中的MSBUILD(因为Connect文章指出此问题已在CLR的下一版本中修复),但也没有提供任何更多详细信息(也许在Beta 2之后已修复)

有没有更好(更自动化)的方法?


2
以我为例,我只需要确保解决方案中的所有项目都运行相同版本的nuget软件包(可以将所有内容全部更新为最新版本)。
2014年

Answers:


576

将“ MSBuild项目构建输出的详细程度”更改为“详细”或以上。为此,请按照下列步骤操作:

  1. 弹出“选项”对话框(工具->选项...)。
  2. 在左侧树中,选择“ 项目和解决方案”节点,然后选择“ 构建并运行”
    • 注意:如果未显示此节点,请确保选中了“ 显示所有设置 ”对话框底部的复选框。
  3. 在出现的工具/选项页面中,根据您的版本将MSBuild项目生成输出详细级别设置为适当的设置:

  4. 生成项目并在输出窗口中查看。

查看MSBuild消息。该ResolveAssemblyReferences任务是MSB3247起源的任务,应有助于您调试此特定问题。

我的具体情况是对SqlServerCe的引用不正确。见下文。我有两个项目引用了SqlServerCe的两个不同版本。我去了较旧版本的项目,删除了参考,然后添加了正确的参考。

Target ResolveAssemblyReferences:
    Consider app.config remapping of assembly "System.Data.SqlServerCe, ..." 
        from Version "3.5.1.0" [H:\...\Debug\System.Data.SqlServerCe.dll] 
        to Version "9.0.242.0" [C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\PublicAssemblies\System.Data.SqlServerCe.dll]
        to solve conflict and get rid of warning.
    C:\WINDOWS\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets : 
        warning MSB3247: Found conflicts between different versions of the same dependent assembly.

您不必打开每个程序集即可确定所引用程序集的版本。

  • 您可以检查每个参考的属性。
  • 打开项目属性,然后检查“参考”部分的版本。
  • 使用文本编辑器打开项目。
  • 使用.Net Reflector。

5
您的解决方案对我来说看起来不错,但是我认为使用“参考”部分查看版本号并不总是有用的。我经常看到VS对我“撒谎”,即使用的是哪个版本与.csproj文件中实际提到的哪个版本。
David Gardiner 2010年

5
@David Gardiner-使用C#项目时,我会同意您的“说谎”声明。以我的经验,C#项目在引用的版本和编译/链接的实际版本上可能会感到困惑。发生这种情况时,我将清理解决方案,手动删除bin和obj文件夹,然后删除%APPDATA%中的临时项目程序集。重建解决方案通常可以解决问题。(VB很少遭受此特定问题的困扰。)
AMissico 2010年

54
告诉人们实际使用“输出”窗口时胜出。构建远不止是F5 +错误列表窗口。
JJS 2010年

2
正如ErikHeemskerk在他的回答中提到的那样,在Visual Studio 2010中,您需要将输出详细程度设置为detail,以查看ResolveAssemblyReferences的输出。
罗宾·克洛尔斯

12
提示:要在详细的构建输出中找到确切的位置,请将文本复制到文本编辑器中,搜索“在同一从属程序集的不同版本之间发现冲突”。
Contango 2011年

133

Mike Hadlow 发布了一个名为AsmSpy的小型控制台应用程序,它很好地列出了每个程序集的引用:

Reference: System.Net.Http.Formatting
        4.0.0.0 by Shared.MessageStack
        4.0.0.0 by System.Web.Http

Reference: System.Net.Http
        2.0.0.0 by Shared.MessageStack
        2.0.0.0 by System.Net.Http.Formatting
        4.0.0.0 by System.Net.Http.WebRequest
        2.0.0.0 by System.Web.Http.Common
        2.0.0.0 by System.Web.Http
        2.0.0.0 by System.Web.Http.WebHost

与依赖MSBuild输出相比,这是到达警告MSB3247底部的更快的方法。


1
AsmSpy非常棒,您只需要记住,您正在寻找版本不匹配的第三方DLL的引用。通常,对标准库的引用中不匹配的版本不会引起这些警告(并且您会看到很多警告)。
Tod Thomson

这是一个很棒的小工具,可帮助我立即解决问题。但是,在我的情况下,它并非完全是第三方DLL,而是对System.Management.Automation.dll的引用,而对MScorlib.dll的引用则不同。
克里斯·吉伦

该工具很好,但是,并非在所有情况下都有效。至少对于.NET 4.5项目,它没有为我显示冲突的参考版本。+ msbuild输出使用路径和所有名称来命名有问题的DLL。
twomm

11
谢谢你们的好心话:)
Mike Hadlow 2013年

您为我节省了一些工作时间!通读详细的输出确实有帮助,但是一旦我完成,就很容易再次使用您的工具进行验证。
Norman H

22

有时@AMissico答案是不够的。就我而言,我无法在“输出”窗口中找到错误,因此我决定通过执行以下步骤来创建日志文件并对其进行分析:

  1. 将生成日志保存到文件... https://msdn.microsoft.com/zh-cn/library/ms171470.aspx

    msbuild MyProject.proj /fl /flp:logfile=MyProjectOutput.log;verbosity=detailed

  2. 查找文本:warning MS...或特定的警告信息:(例如9293行)Found conflicts between different versions...,冲突错误的完整细节将在此消息的上方(例如9277行)There was a conflicts between... 查找错误消息

Visual Studio 2013


在输出中搜索3277的绝佳提示。
sfuqua,

21

我发现(至少在Visual Studio 2010中)您需要将输出详细程度至少设置为“详细”,才能发现问题。

可能是我的问题是以前是GAC参考的参考,但是在我的计算机重新安装后不再是这种情况。


1
转到工具->选项->项目和解决方案->生成并运行以设置输出详细程度。
Farshid

8

我有同样的错误,无法通过其他答案解决。我发现我们可以“合并” NuGet软件包。

  1. 右键单击解决方案
  2. 单击管理Nuget程序包
  3. 合并选项卡并更新到相同版本。

7

针对默认ASP.NET MVC 4 beta生成的此警告, 请参见此处

在这种情况下,可以通过手动编辑项目的.csproj文件来消除此警告的任何类型。

修改……..:参考Include =“ System.Net.Http”

读取......:参考Include =“ System.Net.Http,Version = 4.0.0.0”


1
我遵循了这个步骤,错误消失了。仍然不知道如何或为什么,我从VS2010开始了一个MVC 4项目,然后在VS2012上进行了迁移。但是,添加版本属性会使错误消失。谢谢
MaiOM

6

使用依赖阅读器

使用dep.exe,您可以列出整个文件夹的所有嵌套依赖关系。与grep或awk等unix工具结合使用,可以帮助您解决问题

查找多个版本引用的程序集

$ dep | awk '{ print $1 " " $2; print $4 " " $5 }' | awk '{ if (length(versions[$1]) == 0) versions[$1] = $2; if (versions[$1] != $2) errors[$1] = $1; }  END{ for(e in errors) print e } ' 
System.Web.Http            

此晦涩的命令行运行dep.exe,然后将输出两次通过管道传输到awk,

  • 将父级和子级放在单个列中(默认情况下,每一行包含一个父级和一个子级,以表示该父级依赖于该子级的事实)
  • 然后使用关联数组进行一种“分组依据”

了解此组件如何拉入垃圾箱

$ dep myproject/bin | grep -i System\.Web\.Http
MyProject-1.0.0.0 >> System.Web.Http.Web-5.2.3.0 2 ( FooLib-1.0.0.0 )
MyProject-1.0.0.0 >> System.Web.Http.Web-4.0.0.0 2 ( BarLib-1.0.0.0 )
FooLib-1.0.0.0 > System.Web.Http.Web-5.2.3.0 1
BarLib-1.0.0.0 > System.Web.Http.Web-4.0.0.0 1 

在此示例中,该工具将向您显示System.Web.Http 5.2.3来自对FooLib的依赖关系,而版本4.0.0来自BarLib。

然后您可以选择

  • 说服库的所有者使用相同版本
  • 停止使用一个
  • 在配置文件中添加绑定重定向以使用最新版本

如何在Windows中运行这些东西

如果没有Unix类型的Shell,则需要先下载一个,然后才能运行awkgrep。尝试以下方法之一


4

我也遇到了这个问题,并使用了AMissico的建议也发现了这个问题(尽管必须将详细级别设置为“详细”。

尽管找到了罪魁祸首,但问题实际上还是很直接的。

背景:我将项目从VS2008升级到VS2010。在VS2008中,目标框架是3.5,当我将其引入VS2010时,我将其切换为4(完整)。我还升级了一些第三方组件,包括Crystal报表。

原来,大多数System引用都指向4.0.0.0版,但是其中一些并没有自动更改(System和System.Web.Services),并且仍在查找2.0.0.0。Crystal报表引用的是4.0.0.0,因此这就是发生冲突的地方。只需将光标放在解决方案资源管理器中的第一个系统库上,将光标放在列表上并查找对2.0.0.0的引用,就可以删除并重新添加更新的4.0.0.0版本。

奇怪的是,大多数参考都已正确更新,如果不是针对Crystal报表,我可能永远不会注意到...




1

ASP.NET生成管理器通过按字母顺序浏览这些文件夹来构建网站,对于每个文件夹,它都要弄清其依赖关系,然后先构建依赖关系,然后再构建选定的文件夹。

在这种情况下,有问题的文件夹〜/ Controls被选择从一开始就构建,但出于未知的原因,它在其中将某些控件作为单独的程序集构建,而不是与其他控件在同一程序集内构建(似乎是与某些控件依赖于同一文件夹中的其他控件这一事实有关。

然后,下一个要构建的文件夹(〜/ File-Center / Control)依赖于根文件夹〜/,后者依赖于〜/ Controls,因此,只有这次分开的控件才再次构建文件夹〜/ Controls。现在将它们自己的装配中的“零件”加入到与其他控件相同的装配中,并且仍然引用分离的装配。

因此,此时2个程序集(至少)具有相同的控件,并且构建失败。

尽管我们仍然不知道为什么会发生这种情况,但是我们可以通过将Controls文件夹名称更改为ZControls来解决此问题,这种方式不会在〜/ File-Center / Control之前构建,而只会在之后和这种方式构建正如它应该。


1

快速解决:

右键单击解决方案->管理解决方案的NuGet软件包->在“ 合并”下,您可以查看是否已安装同一软件包的不同版本。卸载不同版本并安装最新版本。


1

有时AutoGenerateBindingRedirects还不够(即使使用也是不够的GenerateBindingRedirectsOutputType)。搜索所有There was a conflict条目并逐个手动修复它们可能很乏味,因此我写了一小段代码来解析日志输出并为您生成它们(转储至stdout):

// Paste all "there was a conflict" lines from the msbuild diagnostics log to the file below
const string conflictFile = @"C:\AssemblyConflicts.txt";

var sb = new StringBuilder();
var conflictLines = await File.ReadAllLinesAsync(conflictFile);
foreach (var line in conflictLines.Where(l => !String.IsNullOrWhiteSpace(l)))
{
    Console.WriteLine("Processing line: {0}", line);

    var lineComponents = line.Split('"');
    if (lineComponents.Length < 2) 
        throw new FormatException("Unexpected conflict line component count");

    var assemblySegment = lineComponents[1];
    Console.WriteLine("Processing assembly segment: {0}", assemblySegment);
    var assemblyComponents = assemblySegment
                              .Split(",")
                              .Select(kv => kv.Trim())
                              .Select(kv => kv.Split("=")
                              .Last())
                              .ToArray();

    if (assemblyComponents.Length != 4) 
        throw new FormatException("Unexpected conflict segment component count");

    var assembly = assemblyComponents[0];
    var version = assemblyComponents[1];
    var culture = assemblyComponents[2];
    var publicKeyToken = assemblyComponents[3];

    Console.WriteLine("Generating assebmly redirect for Assembly={0}, Version={1}, Culture={2}, PublicKeyToken={3}", assembly, version, culture, publicKeyToken);
    sb.AppendLine($"<dependentAssembly><assemblyIdentity name=\"{assembly}\" publicKeyToken=\"{publicKeyToken}\" culture=\"{culture}\" /><bindingRedirect oldVersion=\"0.0.0.0-{version}\" newVersion=\"{version}\" /></dependentAssembly>");
}

Console.WriteLine("Generated assembly redirects:");
Console.WriteLine(sb);

提示:使用MSBuild二进制和结构化日志查看器,仅针对发出警告的项目中的冲突生成绑定重定向(即,there was a conflict对于[ AssemblyConflicts.txt] 上方的代码,仅越过这些行到输入文本文件中即可)。


0

不考虑(内部)依赖关系的最简单方法:

  1. 打开“解决方案资源管理器”。
  2. 点击“显示所有文件”
  3. 展开“参考”
  4. 您会看到一个(或多个)参考与其他图标略有不同的图标。通常,它带有黄色框,建议您记下它。只需将其删除。
  5. 重新添加引用并编译您的代码。
  6. 就这样。

就我而言,MySQL参考存在问题。不知何故,我可以在所有可用参考的列表下列出它的三个版本。我按照上面的过程1到6进行,它对我有用。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.