解决MSB3247 - 发现同一依赖程序集的不同版本之间存在冲突

时间:2009-12-09 01:28:07

标签: .net msbuild clr ndepend

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

有时NDepend可能会有所帮助,但在这种情况下,它没有提供任何进一步的细节。 Like Bob我最终不得不在ILDASM中打开每个程序集,直到找到引用旧版依赖程序集的程序集。

我确实尝试使用VS 2010 Beta 2中的MSBUILD(因为Connect文章表明这​​已经在下一版本的CLR中得到修复)但是它没有提供任何更多细节(可能在Beta 2后修复)

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

16 个答案:

答案 0 :(得分:570)

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

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

  4. 构建项目并查看输出窗口。
  5. 查看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。

答案 1 :(得分:130)

Mike Hadlow已经posted a little console app called 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

这是一种更快速地触及警告MSB3247的底部,而不是依赖于MSBuild输出。

答案 2 :(得分:21)

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

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

答案 3 :(得分:20)

有时@AMissico回答是不够的。在我的情况下,我在输出窗口中找不到错误,因此我决定创建一个日志文件并进行分析,执行以下步骤:

  1. 将构建日志保存到文件中... https://msdn.microsoft.com/en-us/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... Find the error message

  3. Visual Studio 2013

答案 4 :(得分:7)

为默认的ASP.NET MVC 4 beta生成此警告 see here

  

In,可以通过手动编辑来消除任何强制转换此警告   .csproj文件为您的项目。

     

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

     

阅读......:参考包含=“System.Net.Http,Version = 4.0.0.0”

答案 5 :(得分: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。

然后您可以选择

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

如何在Windows中运行这些东西

如果您没有unix类型的shell,则需要先下载一个,然后才能运行awkgrep。请尝试以下其中一项

答案 6 :(得分:6)

我有同样的错误,无法用其他答案搞清楚。我发现我们可以"巩固" NuGet包。

  1. 右键点击解决方案
  2. 点击管理Nuget包
  3. 合并标签并更新为相同版本。

答案 7 :(得分:4)

我也有这个问题并且使用了AMissico的建议也发现了问题(尽管必须将详细程度设置为详细。

虽然找到罪魁祸首后问题实际上非常直接。

背景: 我将我的项目从VS2008升级到了VS2010。在VS2008中,目标框架是3.5,当我把它带到VS2010时,我把它切换到4(Full)。我还升级了一些第三方组件,包括Crystal报告。

事实证明,大多数系统引用都指向版本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报告,我可能永远不会注意到......

答案 8 :(得分:2)

如上所述here,您需要删除未使用的引用,并且警告将会发生。

答案 9 :(得分:2)

我根据Mike Hadlow application: AsmSpy制作了一个应用程序。

我的应用是带有GUI的WPF应用,可以从我的家庭网络服务器下载:AsmSpyPlus.exe

代码位于:GitHub

Gui Sample

答案 10 :(得分:1)

ASP.NET构建管理器通过按字母顺序浏览文件夹来构建网站,并为每个文件夹找出它的依赖关系并首先构建依赖项,然后构建所选文件夹。

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

然后构建的下一个文件夹(〜/ File-Center / Control)依赖于根文件夹〜/依赖于〜/ Controls,所以文件夹〜/ Controls只是这次再次构建控件现在,它们被分离到它们自己的程序集,它们与其他控件连接到同一个程序集,而分离的程序集仍然被引用。

所以在这一点上,2个程序集(至少)具有相同的控件,并且构建失败。

虽然我们仍然不知道为什么会发生这种情况,但是我们能够通过将Controls文件夹名称更改为ZControls来解决它,这种方式它不是在〜/ File-Center / Control之前构建的,只有在这之后才这样做它是按照它应该建造的。

答案 11 :(得分:1)

Quick Fix:

Right click on solution -> Manage NuGet packages for solution -> Under Consolidate you can see if there are different versions of the same package were installed. Uninstall different versions and install the latest one.

答案 12 :(得分:1)

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

// 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 Binary and Structured Log Viewer并仅针对发出警告的项目中的冲突生成绑定重定向(即,仅对于[[...] {1}}]。

答案 13 :(得分:0)

一种最简单的方法,没有考虑到(内部)依赖关系:

  1. 打开“解决方案资源管理器”。
  2. 点击“显示所有文件”
  3. 展开“参考”
  4. 您会看到一个(或多个)引用的图标与其他引用略有不同。通常,它是黄色框,建议你记下它。只需删除它。
  5. 添加引用并编译代码。
  6. 就是这样。
  7. 就我而言,MySQL引用存在问题。不知何故,我可以在所有可用引用列表下列出它的三个版本。我按照上面的过程1到6进行操作,它对我有用。

答案 14 :(得分:0)

Visual Studio for Mac社区补充:

由于AMissico's answer需要更改日志级别,并且ASMSpy和ASMSpyPlus都不可用作跨平台解决方案,因此这是Visual Studio for Mac的一个简短补充:

  

https://docs.microsoft.com/en-us/visualstudio/mac/compiling-and-building

它位于 Visual Studio社区→首选项...→项目→构建日志→详细程度

答案 15 :(得分:0)

如果您有剃须刀,请删除解决方案上所有未使用的参考。