-
-
Save brianlow/1553265 to your computer and use it in GitHub Desktop.
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; } | |
} | |
} | |
} |
@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.
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; }
}
}
}
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
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
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
- Sub-Reference C
- Reference A
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?
I get a ton of results for "Possible conflicts for mscorlib" is this expected?
awesome works great...