Mon
Jan 25
2010

Find Conflicting Assembly References

A small test to help resolve the compiler warning:

warning MSB3247: Found conflicts between different versions of the same dependent assembly.

Point it to the build folder of your project and it will look for referenced assemblies with the same short name but different full names.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using NUnit.Framework;
 
namespace MyProject
{
    [TestFixture]
    public class UtilityTest
    {
        [Test]
        public void FindConflictingReferences()
        {
            var assemblies = GetAllAssemblies(@"E:\dev\myapp\myproject\bin\debug");
 
            var references = GetReferencesFromAllAssemblies(assemblies);
 
            var groupsOfConflicts = FindReferencesWithTheSameShortNameButDiffererntFullNames(references);
 
            foreach (var group in groupsOfConflicts)
            {
                Console.Out.WriteLine("Possible conflicts for {0}:", group.Key);
                foreach (var reference in group)
                {
                    Console.Out.WriteLine("{0} references {1}",
                                          reference.Assembly.Name.PadRight(25),
                                          reference.ReferencedAssembly.FullName);
                }
            }
        }
 
        private IEnumerable<IGrouping<string, Reference>> FindReferencesWithTheSameShortNameButDiffererntFullNames(List<Reference> references)
        {
            return from reference in references
                   group reference by reference.ReferencedAssembly.Name
                       into referenceGroup
                       where referenceGroup.ToList().Select(reference => reference.ReferencedAssembly.FullName).Distinct().Count() > 1
                       select referenceGroup;
        }
 
        private List<Reference> GetReferencesFromAllAssemblies(List<Assembly> assemblies)
        {
            var references = new List<Reference>();
            foreach (var assembly in assemblies)
            {
                foreach (var referencedAssembly in assembly.GetReferencedAssemblies())
                {
                    references.Add(new Reference
                    {
                        Assembly = assembly.GetName(),
                        ReferencedAssembly = referencedAssembly
                    });
                }
            }
            return references;
        }
 
        private List<Assembly> GetAllAssemblies(string path)
        {
            var files = new List<FileInfo>();
            var directoryToSearch = new DirectoryInfo(path);
            files.AddRange(directoryToSearch.GetFiles("*.dll", SearchOption.AllDirectories));
            files.AddRange(directoryToSearch.GetFiles("*.exe", SearchOption.AllDirectories));
            return files.ConvertAll(file => Assembly.LoadFile(file.FullName));
        }
 
        private class Reference
        {
            public AssemblyName Assembly { get; set; }
            public AssemblyName ReferencedAssembly { get; set; }
        }
 
    }
}

6 Comments so far

  1. Tim Coulter February 9th, 2010 6:26 am

    Many thanks for this Brian – it was a timely and effective solution for an irritating problem.

  2. Steffen S February 17th, 2010 8:56 am

    Thanks that helped! Nice to have around.

  3. Rene Schulte April 22nd, 2010 4:41 am

    Or just look at the Output window after the build. ;)

  4. Felix Collins May 30th, 2010 4:18 pm

    Problem 1
    I find that this picks up mscorlib 2.0.0.0 and 1.0.5000.0 for most of my projects. Why would this be? As far as I can see the project file does not specify which mscorlib to use. I check all the projects in the solution using coolcommands ref manager and they all report mscorlib 2.0.0.0. I suppose some of the third party libs I reference could have been built to reference mscorlib 1.0.5000.0.

    Problem 2
    I get a build warning for different versions of DirectShowLib. But the test does not show this up. This is caused by a third party lib referencing the older version.

    “Consider app.config remapping of assembly “DirectShowLib-2005, from Version “2.0.0.0″ [] to Version “2.1.0.0″ to solve conflict and get rid of warning.” (edited for clarity)

  5. Brian May 30th, 2010 9:10 pm

    @Rene: the Output window tells you which assembly is conflicted (which is often enough) but doesn’t tell you which assemblies are causing the conflict.

    @Felix: perhaps the problem is 2 levels deep. This test only looks at immediate references and not references of references (e.g. your project -> A.dll -> B.dll -> mscorlib 1.0.5000.0). You’ll need to make GetReferencesFromAllAssemblies() a little smarter to find these problems.

  6. Chad June 25th, 2010 9:32 am

    Wow, I’ve just spent 2 hours trying to find this one rogue reference and this tool just found it for me in 5 seconds. Much thanks!

Leave a reply

© 2009 Brian Low. All rights reserved.