57

I have a collection of DLLs(say 20). How do I find out all the DLLs on which one specific DLL (say DLL A) is depending upon?

kayleeFrye_onDeck
  • 6,648
  • 5
  • 69
  • 80
Abhijeet
  • 13,562
  • 26
  • 94
  • 175

7 Answers7

58

If you mean programmatically, use Assembly.GetReferencedAssemblies.

You can use that recursively to find all the assemblies you need. (So you find the dependencies of X, then the dependencies of the dependencies, etc.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 1
    you will need to include "using System.Reflection;" – greenfeet Jul 20 '15 at 08:52
  • 6
    @greenfeet: Not necessarily - you could use `var assemblies = typeof(Foo).Assembly.GetReferencedAssemblies();` for example. In general, it's not worth adding all the namespaces used by all the types referenced in answers - particularly not when there are links to the types in question. I kind of assume that readers understand enough of the C# language to know when to add a `using` directive. – Jon Skeet Jul 20 '15 at 08:56
  • Could you avoid adding `using System.Reflection` for the dependencies of the dependencies? Wouldn't you have to invoke Assembly.LoadWithPartialName (or something similar) at some point? – theoski Oct 09 '15 at 17:14
  • 2
    @theoski: Using directives just mean you don't have to fully-qualify names... I don't really see what you're asking. – Jon Skeet Oct 09 '15 at 17:17
  • Sorry, I was thinking you meant something else when you said 'links to the types in question', when I should have known you were talking about the [Assembly.GetReferencedAssemblies](http://msdn.microsoft.com/en-us/library/system.reflection.assembly.getreferencedassemblies.aspx) link. I thought maybe there was some way to avoid using statements in the C# (not that I would want to). I was just curious. – theoski Oct 12 '15 at 17:44
  • Accepted answer will only work for .NET libs and execs; mentioning because OP does not specify that they know the origin of the files to be inspected, only that it's a C# question. – kayleeFrye_onDeck Apr 27 '17 at 23:09
  • 1
    @kayleeFrye_onDeck: Given that it was accepted and no other information was provided, I think it's reasonable to assume it *is* about .NET assemblies. – Jon Skeet Apr 28 '17 at 06:28
  • 1
    I understand that might have been the intent, @JonSkeet, but as I ran across this question while looking for something less specific in regards to DLLs, the description of the question, its tags, and lack of mentioning assemblies vs. generalized DLLs can cause confusion. I'm not questioning the validity of your answer for the OP. – kayleeFrye_onDeck Apr 28 '17 at 17:31
17

Since the question is tagged "C#", I would assume you are talking about managed dlls (assemblies). In that case, dependencywalker is not useful. If you want to do that with a program, good ones are dotPeek by JetBrians and Reflector by RedGate. Or you can even use the object inspector in Visual Studio.

However, it can be a long process and cumbersome too. I would write a short C# program/F# script that uses Assembly.GetReferencedAssemblies, as Jon mentioned.

If instead you want to examine native DLLs dependencies with a program (C# code), you have to walk the examine the PE file (the MS dll and exe file format) and its IAT (import address table). Not easy, but not impossible...

I would start here on MSDN and here to understand PE sections, and use a managed library to read it (there are many, including some from the Mono project (I'm thinking of Cecil, it should work with native binaries too); in the past I have used this one from the good John Gough.

Lorenzo Dematté
  • 7,638
  • 3
  • 37
  • 77
14

All answer credit goes to previous authors for the usage of Assembly.GetReferencedAssemblies. This is just a write-and-forget C# console app that works solely for .NET assemblies. return 0 on assemblies you were able to check, and when successful, outputs them to STDOUT. Everything else will return 1 and print some kind of error output. You can grab the gist here.

using System;
using System.Reflection;
using System.IO;
namespace DotNetInspectorGadget
{
    class DotNetInspectorGadget 
    {
        static int Main(string[] args) 
        {
          if(args.GetLength(0) < 1)
          {
            Console.WriteLine("Add a single parameter that is your" +
            " path to the file you want inspected.");
            return 1;
          }
          try {
                var assemblies = Assembly.LoadFile(@args[0]).GetReferencedAssemblies();

                if (assemblies.GetLength(0) > 0)
                {
                  foreach (var assembly in assemblies)
                  {
                    Console.WriteLine(assembly);
                  }
                  return 0;
                }
          }
          catch(Exception e) {
            Console.WriteLine("An exception occurred: {0}", e.Message);
            return 1;
          } finally{}

            return 1;
        }
    }
}

Usage:

call %cd%\dotnet_inspector_gadget.exe C:\Windows\Microsoft.NET\assembly\GAC_64\Microsoft.ConfigCI.Commands\v4.0_10.0.0.0__31bf3856ad364e35\Microsoft.ConfigCI.Commands.dll

Output:

mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Management.Automation, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Management, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
kayleeFrye_onDeck
  • 6,648
  • 5
  • 69
  • 80
11

You can use dependency walker http://www.dependencywalker.com to figure this out. Take note on the difference between x32 and x64 though.

Dependency Walker is a free utility that scans any 32-bit or 64-bit Windows module (exe, dll, ocx, sys, etc.) and builds a hierarchical tree diagram of all dependent modules.

Alex
  • 7,901
  • 1
  • 41
  • 56
Aniket Inge
  • 25,375
  • 5
  • 50
  • 78
7

For .NET assemblies, a terrific tool to view the assemblies an assembly is dependent on is AsmSpy.

Alexander van Trijffel
  • 2,916
  • 1
  • 29
  • 31
1

If you want the DLL's (the files) then, Assembly.GetReferencedAssemblies will also return the .Net Framework assemblies.

Here is a simple code snippet that will get the dll's it can find in the current directory (and also include some other related files):

private readonly string[] _extensions = { ".dll", ".exe", ".pdb", ".dll.config", ".exe.config" };

private string[] GetDependentFiles(Assembly assembly)
{
    AssemblyName[] asm = assembly.GetReferencedAssemblies();
    List<string> paths = new List<string>(asm.Length);
    for (int t = asm.Length - 1; t >= 0; t--)
    {
        for (int e = _extensions.Length - 1; e >= 0; e--)
        {
            string path = Path.GetFullPath(asm[t].Name + _extensions[e]);
            if (File.Exists(path)) paths.Add(path);
        }
    }

    return paths.ToArray();
}

You can call it like so: MessageBox.Show(string.Join("\r\n", GetDependentFiles(Assembly.GetEntryAssembly())));

Louis Somers
  • 2,560
  • 3
  • 27
  • 57
0

This example shows a situation where we also want to display recursive dependencies. Tested with .net 4.5.2


using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Windows.Forms;

var assemblyPath = @"C:\Temp\Some-Assembly.dll";
var assembly = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
var indent = 0;
PrintDependencies(assembly.GetReferencedAssemblies(), ref indent, new List<string>());

private void PrintDependencies(
    IEnumerable<AssemblyName> names, 
    ref int indent, 
    ICollection<string> visited)
{
    indent++;
    foreach (var name in names)
    {
        Print(name, indent);
        if (visited.Contains(name.FullName)) continue;
        visited.Add(name.FullName);
        var assembly = Assembly.ReflectionOnlyLoad(name.FullName);
        PrintDependencies(assembly.GetReferencedAssemblies(), ref indent, visited);
    }
    indent--;
}

// Rich text box was used, but can be anything else
private void Print(AssemblyName name, int indent) 
    => richTextBox.AppendText($"{new string('-', indent * 4)}{name.FullName}{Environment.NewLine}");

enter image description here

Daniel Dušek
  • 13,683
  • 5
  • 36
  • 51