使用msbuild进行编译时,.NET 3.5解决方案最终出现此警告。
有时NDepend可能会有所帮助,但在这种情况下,它没有提供任何更多详细信息。像鲍勃一样,我最终不得不诉诸于ILDASM中的每个程序集,直到我找到一个引用较旧版本的从属程序集的程序。
我确实尝试使用VS 2010 Beta 2中的MSBUILD(因为Connect文章指出此问题已在CLR的下一版本中修复),但也没有提供任何更多详细信息(也许在Beta 2之后已修复)
有没有更好(更自动化)的方法?
使用msbuild进行编译时,.NET 3.5解决方案最终出现此警告。
有时NDepend可能会有所帮助,但在这种情况下,它没有提供任何更多详细信息。像鲍勃一样,我最终不得不诉诸于ILDASM中的每个程序集,直到我找到一个引用较旧版本的从属程序集的程序。
我确实尝试使用VS 2010 Beta 2中的MSBUILD(因为Connect文章指出此问题已在CLR的下一版本中修复),但也没有提供任何更多详细信息(也许在Beta 2之后已修复)
有没有更好(更自动化)的方法?
Answers:
将“ MSBuild项目构建输出的详细程度”更改为“详细”或以上。为此,请按照下列步骤操作:
在出现的工具/选项页面中,根据您的版本将MSBuild项目生成输出详细级别设置为适当的设置:
查看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.
您不必打开每个程序集即可确定所引用程序集的版本。
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底部的更快的方法。
有时@AMissico答案是不够的。就我而言,我无法在“输出”窗口中找到错误,因此我决定通过执行以下步骤来创建日志文件并对其进行分析:
将生成日志保存到文件... https://msdn.microsoft.com/zh-cn/library/ms171470.aspx
msbuild MyProject.proj /fl /flp:logfile=MyProjectOutput.log;verbosity=detailed
查找文本:warning MS...
或特定的警告信息:(例如9293行)Found conflicts between different versions...
,冲突错误的完整细节将在此消息的上方(例如9277行)There was a conflicts between...
Visual Studio 2013
使用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。
然后您可以选择
如果没有Unix类型的Shell,则需要先下载一个,然后才能运行awk
和grep
。尝试以下方法之一
我也遇到了这个问题,并使用了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报表,我可能永远不会注意到...
我基于Mike Hadlow应用程序AsmSpy创建了一个应用程序。
我的应用程序是带有GUI的WPF应用程序,可以从我的家庭Web服务器AsmSpyPlus.exe下载。
ASP.NET生成管理器通过按字母顺序浏览这些文件夹来构建网站,对于每个文件夹,它都要弄清其依赖关系,然后先构建依赖关系,然后再构建选定的文件夹。
在这种情况下,有问题的文件夹〜/ Controls被选择从一开始就构建,但出于未知的原因,它在其中将某些控件作为单独的程序集构建,而不是与其他控件在同一程序集内构建(似乎是与某些控件依赖于同一文件夹中的其他控件这一事实有关。
然后,下一个要构建的文件夹(〜/ File-Center / Control)依赖于根文件夹〜/,后者依赖于〜/ Controls,因此,只有这次分开的控件才再次构建文件夹〜/ Controls。现在将它们自己的装配中的“零件”加入到与其他控件相同的装配中,并且仍然引用分离的装配。
因此,此时2个程序集(至少)具有相同的控件,并且构建失败。
尽管我们仍然不知道为什么会发生这种情况,但是我们可以通过将Controls文件夹名称更改为ZControls来解决此问题,这种方式不会在〜/ File-Center / Control之前构建,而只会在之后和这种方式构建正如它应该。
有时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
] 上方的代码,仅越过这些行到输入文本文件中即可)。
由于AMissico的答案需要更改日志级别,并且ASMSpy和ASMSpyPlus都不可用作跨平台解决方案,因此这是Visual Studio for Mac的简短补充:
https://docs.microsoft.com/zh-cn/visualstudio/mac/compiling-and-building
它位于Visual Studio社区 →首选项...→项目→构建日志→详细程度