Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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; }
}
}
}
@shaydoc

This comment has been minimized.

Copy link

@shaydoc shaydoc commented May 29, 2013

good job!, found this very helpful..

@isaac-l

This comment has been minimized.

Copy link

@isaac-l isaac-l commented Sep 2, 2013

+1 nice one

@Tiggerito

This comment has been minimized.

Copy link

@Tiggerito Tiggerito commented Sep 12, 2013

Worked like a charm. Thanks.

@dprothero

This comment has been minimized.

Copy link

@dprothero dprothero commented Apr 16, 2014

Fantastic!

@RosanaRufer

This comment has been minimized.

Copy link

@RosanaRufer RosanaRufer commented May 27, 2014

Thank you so much

@krisztianb

This comment has been minimized.

Copy link

@krisztianb krisztianb commented Jun 25, 2014

This does not work for me. I get a System.BadImageFormatException at the line:

return files.ConvertAll(file => Assembly.LoadFile(file.FullName));
@emresebat

This comment has been minimized.

Copy link

@emresebat emresebat commented Jul 10, 2014

Hi
İf you receive System.BadImageFormatException, just try compiling this utility project not for Any CPU but the same as the project you are trying to check, like x86 or x64.

@ryios

This comment has been minimized.

Copy link

@ryios ryios commented Aug 14, 2014

The BadImageFormatException is because this utility doesn't consider the possibility of non .net images being in the bin folders, which is highly possible. You can put native dll's in the bin folder and load them with DllImport calls.

Just change some lines,

    private List<Reference> GetReferencesFromAllAssemblies(List<Assembly> assemblies)
    {
        var references = new List<Reference>();
        foreach (var assembly in assemblies)
        {
            if (assembly == null)
                continue;

And

    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;
            }

        });
    }
@WaffleSouffle

This comment has been minimized.

Copy link

@WaffleSouffle WaffleSouffle commented Dec 11, 2014

Forked, incorporated ryios changes, made into a short program accepting directory paths on the command line.
https://gist.github.com/WaffleSouffle/bcc3eaebaa7a7cadcab6

@mikesocha3

This comment has been minimized.

Copy link

@mikesocha3 mikesocha3 commented Jul 7, 2015

This is great!! Also it provides a template for any other projects you might be interested in involving dlls and references etc... For example, I am thinking of writing a project to find all unused references (no small task X( )

@collinsauve

This comment has been minimized.

Copy link

@collinsauve collinsauve commented Nov 24, 2015

FYI I've created a full repo for this with a VS2015 csproj (to compile it).

https://github.com/collinsauve/FindConflictingReferences

@deepdrunk

This comment has been minimized.

Copy link

@deepdrunk deepdrunk commented Jan 6, 2016

Sorry for stupid question but how to use this tool ?I want to see conflicting references in my project but how exactly to use it,attach to what process ?When i try to attach to my project process it say unable to attach to the process,debugger already attached.

@crazyjat

This comment has been minimized.

Copy link

@crazyjat crazyjat commented Jan 12, 2016

Would be nice for us normal people to have some documentation for how to use this.

@czeshirecat

This comment has been minimized.

Copy link

@czeshirecat czeshirecat commented Jan 28, 2016

Same here. Could we have some instructions on how to use this unit please. Thanks :)

@sjclark76

This comment has been minimized.

Copy link

@sjclark76 sjclark76 commented Feb 23, 2016

awesome works great...

@HSBallina

This comment has been minimized.

Copy link

@HSBallina HSBallina commented Mar 22, 2016

@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

This comment has been minimized.

Copy link

@daryllabar daryllabar commented Jun 23, 2016

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

This comment has been minimized.

Copy link

@dagrooms52 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

This comment has been minimized.

Copy link

@wullumpie 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

This comment has been minimized.

Copy link

@qJake 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?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.