432
votes

A .NET 3.5 solution ended up with this warning when compiling with msbuild.

Sometimes NDepend might help out but in this case it didn't give any further details. Like Bob I ended up having to resort to opening each assembly in ILDASM until I found the one that was referencing an older version of the dependant assembly.

I did try using MSBUILD from VS 2010 Beta 2 (as the Connect article indicated this was fixed in the next version of the CLR) but that didn't provide any more detail either (maybe fixed post Beta 2)

Is there a better (more automated) approach?

16
In my case I just had to make sure all the projects in the solution were running the same version of nuget packages (can simply update all to the latest).Michael

16 Answers

584
votes

Change the "MSBuild project build output verbosity" to "Detailed" or above. To do this, follow these steps:

  1. Bring up the Options dialog (Tools -> Options...).
  2. In the left-hand tree, select the Projects and Solutions node, and then select Build and Run.
    • Note: if this node doesn't show up, make sure that the checkbox at the bottom of the dialog Show all settings is checked.
  3. In the tools/options page that appears, set the MSBuild project build output verbosity level to the appropriate setting depending on your version:

  4. Build the project and look in the output window.

Check out the MSBuild messages. The ResolveAssemblyReferences task, which is the task from which MSB3247 originates, should help you debug this particular issue.

My specific case was an incorrect reference to SqlServerCe. See below. I had two projects referencing two different versions of SqlServerCe. I went to the project with the older version, removed the reference, then added the correct reference.

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.

You do not have to open each assembly to determine the versions of referenced assemblies.

  • You can check the Properties of each Reference.
  • Open the project properties and check the versions of the References section.
  • Open the projects with a Text Editor.
  • Use .Net Reflector.
140
votes

Mike Hadlow has posted a little console app called AsmSpy that rather nicely lists each assembly's references:

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

This is a much quicker way to get to the bottom of the warning MSB3247, than to depend on the MSBuild output.

24
votes

Sometime @AMissico answer is not enough. In my case, I couldn't find the error in the Output windows so I decided to create a log file and analyze it, by doing the following steps:

  1. Saving the build log to a file... https://msdn.microsoft.com/en-us/library/ms171470.aspx

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

  2. Find the text: warning MS... or the specific warning info: (e.g. line 9293) Found conflicts between different versions... and the full detail of the conflict error will be above of this message (e.g. line 9277) There was a conflicts between... Find the error message

Visual Studio 2013

21
votes

I found that (at least in Visual Studio 2010) you need to set the output verbosity to at least Detailed to be able to spot the problem.

It might be that my problem was a reference that was previously a GAC reference, but that was no longer the case after my machine's reinstall.

9
votes

I had the same error and could not figure it out with the other answers. I found that we can "Consolidate" NuGet packages.

  1. Right click on the solution
  2. Click Manage Nuget Packages
  3. Consolidate tab and update to the same version.
7
votes

This warning generated for default ASP.NET MVC 4 beta see here

In, any cast this Warning can be eliminated by manually editing the .csproj file for your project.

modify........: Reference Include="System.Net.Http"

to read ......: Reference Include="System.Net.Http, Version=4.0.0.0"

6
votes

Use a dependency reader

Using dep.exe you can list out all the nested dependencies of an entire folder. Combined with unix tools like grep or awk, it can help you to solve your problem

Finding assemblies being referenced in more than one version

$ 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            

This obscure command line runs dep.exe then pipes the output twice to awk to

  • put the parent and child in a single column (by default each line contains one parent and a child to express the fact that this parent depends of that child)
  • then do a kind of 'group by' using an associative array

Understanding how this assembly got pulled in your bin

$ 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 

In this example, the tool would show you that System.Web.Http 5.2.3 comes from your dependency to FooLib whereas the version 4.0.0 comes from BarLib.

Then you have the choice between

  • convincing the owners of the libs to use the same version
  • stop using one them
  • adding binding redirects in your config file to use the latest version

How to run these thing in Windows

If you don't have a unix type shell you'll need to download one before being able to run awkand grep. Try one of the following

4
votes

I had this problem too and used AMissico's advice too discover the problem (Although had to set verbosity level to Detailed.

The problem was actually quite straight forward though after finding the culprit.

Background: I upgraded my project from VS2008 to VS2010. In VS2008 the target framework was 3.5 and when I brought it into VS2010 I switched it to 4 (Full). I also upgraded some third party components including Crystal reports.

It turned out most of System references where pointing at version 4.0.0.0 but a couple had not been automatically changed (System and System.Web.Services) and were still looking at 2.0.0.0. Crystal reports is referencing 4.0.0.0 and so this was where the conflicts were occuring. Simply putting the cursor at the first System library in the solution explorer, cursor down the list and looking for any references to 2.0.0.0, removing and re-adding newer 4.0.0.0 version did the trick.

The strange this was that most of the references had been correctly updated and if it weren't for Crystal reports, I probably would never had noticed...

2
votes

I made an application based on Mike Hadlow application: AsmSpy.

My app is a WPF app with GUI and can be download from my home webserver: AsmSpyPlus.exe.

Code is available at: GitHub

Gui Sample

2
votes

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.

2
votes

As mentioned here, you need to remove the unused references and the warnings will go.

1
votes

ASP.NET build manager is building the website by going through the folders alphabetically, and for each folder it figures out it dependencies and builds the dependencies first and then the selected folder.

In this case the problematic folder which is ~/Controls, is selected to be built at the beginning, from yet an unknown reason, it builds some of the controls there as a separate assembly instead of inside the same assembly as other controls (seems to be connected to the fact that some controls are dependent on other controls in the same folder).

Then the next folder which is built (~/File-Center/Control) is dependent on the root folder ~/ which is dependent on ~/Controls, so the folder ~/Controls is being built again only this time the controls which were separated to their own assembly are now joined to the same assembly as other controls with the separated assembly still being referenced.

So at this point 2 assembly (at least) have the same controls and the build fails.

Although we still don't know why this happened, we were able to work around it by changing the Controls folder name to ZControls, this way it is not built before ~/File-Center/Control, only after and this way it is built as it should.

1
votes

Sometimes AutoGenerateBindingRedirects isn't enough (even with GenerateBindingRedirectsOutputType). Searching for all the There was a conflict entries and fixing them manually one by one can be tedious, so I wrote a small piece of code that parses the log output and generates them for you (dumps to 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);

Tip: use MSBuild Binary and Structured Log Viewer and only generate binding redirects for the conflicts in the project that emits the warning (that is, only past those there was a conflict lines to the input text file for the code above [AssemblyConflicts.txt]).

0
votes

A simplest way without without one taking into account of (internal) dependencies :

  1. Open "Solution Explorer".
  2. Click on "Show all files"
  3. Expand "References"
  4. You'll see one (or more) reference(s) with slightly different icon than the rest. Typically, it is with yellow box suggesting you to take a note of it. Just remove it.
  5. Add the reference back and compile your code.
  6. That's all.

In my case, there was a problem with MySQL reference. Somehow, I could list three versions of it under the list of all available references. I followed process 1 through 6 above and it worked for me.

0
votes

Visual Studio for Mac Community addition:

As AMissico's answer requires changing the log level, and neither ASMSpy nor ASMSpyPlus are available as a cross-platform solution, here is a short addition for Visual Studio for Mac:

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

It's in Visual Studio Community → Preferences... → Projects → Build Log → verbosity

0
votes

If you have resharper, remove all unused reference on your solution.