Skip to content

Instantly share code, notes, and snippets.

@brianlow
Created January 3, 2012 03:04
Show Gist options
  • Star 88 You must be signed in to star a gist
  • Fork 27 You must be signed in to fork a gist
  • Save brianlow/1553265 to your computer and use it in GitHub Desktop.
Save brianlow/1553265 to your computer and use it in GitHub Desktop.
Find conflicting assembly references
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; }
}
}
}
@sjclark76
Copy link

awesome works great...

@HSBallina
Copy link

@deepdrunk; either create a unit test proj in your solution and copy paste it to a test class there or just use either of the programs that @WaffleSouffle or @collinsauve created.

@daryllabar
Copy link

Here is an XUnit Version with ryios's changes incorporated:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using Xunit;
using Xunit.Abstractions;

namespace MyProject
{
    public class UtilityTest
    {
        private ITestOutputHelper _output;
        public UtilityTest(ITestOutputHelper output) { _output = output; }

        [Fact]
        public void FindConflictingReferences()
        {
            var assemblies = GetAllAssemblies(@"C:\_Dev\Defenders\CRM\Dev\Defender.CRM\Defender.Xrm.Job.Plugins.Tests\bin\Debug");

            var references = GetReferencesFromAllAssemblies(assemblies);

            var groupsOfConflicts = FindReferencesWithTheSameShortNameButDiffererntFullNames(references);

            foreach (var group in groupsOfConflicts)
            {
                _output.WriteLine("Possible conflicts for {0}:", group.Key);
                foreach (var reference in group)
                {
                    _output.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)
            {
                if (assembly == null)
                {
                    continue;
                }

                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 => {
                try
                {
                    Assembly asm = Assembly.LoadFile(file.FullName);
                    return asm;
                }
                catch (System.BadImageFormatException)
                {
                    return null;
                }

            });
        }

        private class Reference
        {
            public AssemblyName Assembly { get; set; }
            public AssemblyName ReferencedAssembly { get; set; }
        }

    }
}

@dagrooms52
Copy link

dagrooms52 commented Jun 24, 2016

I updated this to make it a little faster (and find all project files in the solution). It uses async await to not block your other tests. https://gist.github.com/dagrooms52/f5179304f759a1ff7d0332c87dad487c

@wullumpie
Copy link

wullumpie commented Dec 6, 2016

Thank u @colinsauve for the project! Works good and helped me pinpoint the troubling dll. (I found that removing that particular dll from the project solved my problem)
Willem

@qJake
Copy link

qJake commented Feb 14, 2017

This doesn't cover cases where the reference is nested in another assembly, does it?

Consider the following case:

  • My Project
    • Reference A
      • CoolLibrary 1.0
    • Reference B
      • Sub-Reference C
        • CoolLibrary 1.1

I'm getting the "Found conflicts between different versions..." warning and I believe this scenario is the reason for it, but I don't think this test output includes this level of references. How can we modify it so that it searches references of references?

@VictorioBerra
Copy link

I get a ton of results for "Possible conflicts for mscorlib" is this expected?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment