|
Mon
Jan 25 2010 |
Find Conflicting Assembly References |
|
A small test to help resolve the compiler warning:
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; } } } } |
Many thanks for this Brian – it was a timely and effective solution for an irritating problem.
Thanks that helped! Nice to have around.
Or just look at the Output window after the build.
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)
@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.
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!