Skip to content

Instantly share code, notes, and snippets.

@jdpilgrim
Last active August 29, 2015 14:21
Show Gist options
  • Save jdpilgrim/b7f2cf9d36241f57082f to your computer and use it in GitHub Desktop.
Save jdpilgrim/b7f2cf9d36241f57082f to your computer and use it in GitHub Desktop.
Does a recursive search of all references (dependant dlls). Invoking main with arg[0]=ROOT will search all deep dependancies of ROOT and print those in the same directory as ROOT
using System;
using System.Reflection;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
public class MyTree<K, V> : Dictionary<K, MyTree<K, V>>
{
public V Value { get; set; }
}
//http://www.pcreview.co.uk/forums/net-dependency-walker-t1227184.html
//http://stackoverflow.com/questions/1373100/how-to-add-folder-to-assembly-search-path-at-runtime-in-net
public class DependencyReporter
{
private string _baseAssemblyName;
private AppDomain currentDomain = AppDomain.CurrentDomain;
private Assembly rootAssm;
public Assembly RootAssembly { get { return rootAssm; } }
public string RootAssemblyDirectory { get;set; }
private Dictionary<string, MyTree<AssemblyName, Assembly>> all = new Dictionary<string, MyTree<AssemblyName, Assembly>>();
private MyTree<AssemblyName, Assembly> root = new MyTree<AssemblyName, Assembly>();
public MyTree<AssemblyName, Assembly> Root { get { return root; } }
public DependencyReporter(string baseAssemblyName)
{
_baseAssemblyName = baseAssemblyName;
currentDomain.AssemblyResolve += new ResolveEventHandler(LoadFromSameFolder);
Hashtable alreadyLoaded = new Hashtable();
rootAssm = Assembly.LoadFrom(baseAssemblyName);
RootAssemblyDirectory = Path.GetDirectoryName(rootAssm.Location);
PopulateDependencyTree(rootAssm, root);
}
void PopulateDependencyTree(Assembly assm, MyTree<AssemblyName, Assembly> references)
{
AssemblyName fqn = assm.GetName();
references.Value = assm;
foreach (AssemblyName name in assm.GetReferencedAssemblies())
{
MyTree<AssemblyName, Assembly> subTree;
if(!all.TryGetValue(name.FullName, out subTree))
{
subTree = new MyTree<AssemblyName, Assembly>();
all.Add(name.FullName, subTree);
Assembly referenced = Assembly.Load(name);
PopulateDependencyTree(referenced, subTree);
references.Add(name, subTree);
}
else
{
// empty to break loop
references.Add(name, new MyTree<AssemblyName, Assembly>() { Value = subTree.Value });
}
}
}
private Assembly LoadFromSameFolder(object sender, ResolveEventArgs args)
{
Assembly from_same_dir = LoadFromPath(args, Path.GetDirectoryName(rootAssm.Location));
return from_same_dir;
}
private Assembly LoadFromPath(ResolveEventArgs args, string folderPath)
{
string assemblyPath = Path.Combine(folderPath, new AssemblyName(args.Name).Name + ".dll");
if (File.Exists(assemblyPath) == false)
{
return null;
}
Assembly assembly = Assembly.LoadFrom(assemblyPath);
return assembly;
}
static void Main(string[] args)
{
try
{
string name;
if (args.Length == 0)
{
Console.WriteLine("Usage: DependencyReporter <assembly1>");
}
else
name = args[0];
Console.WriteLine(name);
var depRep = new DependencyReporter(name);
//Print(depRep, depRep.Root, 0);
var dlls = depRep.Root
.Traverse(tree => tree.Value).Select(kvp => kvp.Value)
.Where(tree => Path.GetDirectoryName(tree.Value.Location) == depRep.RootAssemblyDirectory)
.Select(tree => Path.GetFileName(tree.Value.Location))
.OrderBy(dir => dir)
.Distinct();
foreach(string dll in dlls)
{
Console.WriteLine(dll);
}
}
catch(Exception e)
{
Console.WriteLine(e);
}
}
}
public static class Extensions {
public static IEnumerable<T> Traverse<T>(this IEnumerable<T> items,
Func<T, IEnumerable<T>> childSelector)
{
var stack = new Stack<T>(items);
while(stack.Any())
{
var next = stack.Pop();
yield return next;
foreach(var child in childSelector(next))
stack.Push(child);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment