21

How can I get the list of all DLL dependencies of a given DLL or EXE file?

In other words, I'd like to do the same as the "Dependency walker" tool, but programmatically.

What is the Windows (ideally .NET) API for that?

John Topley
  • 113,588
  • 46
  • 195
  • 237
sthiers
  • 3,489
  • 5
  • 34
  • 47

6 Answers6

13

You can use EnumProcessModules function. Managed API like kaanbardak suggested won't give you a list of native modules.

For example see this page on MSDN

If you need to statically analyze your dll you have to dig into PE format and learn about import tables. See this excellent tutorial for details.

Paul
  • 25,812
  • 38
  • 124
  • 247
aku
  • 122,288
  • 32
  • 173
  • 203
4

NOTE: Based on the comments from the post below, I suppose this might miss unmanaged dependencies as well because it relies on reflection.

Here is a small c# program written by Jon Skeet from bytes.com on a .NET Dependency Walker

using System;
using System.Reflection;
using System.Collections;

public class DependencyReporter
{
    static void Main(string[] args)
    {
        //change this line if you only need to run the code one:
        string dllToCheck = @"";

        try
        {
            if (args.Length == 0)
            {
                if (!String.IsNullOrEmpty(dllToCheck))
                {
                    args = new string[] { dllToCheck };
                }
                else
                {
                    Console.WriteLine
                        ("Usage: DependencyReporter <assembly1> [assembly2 ...]");
                }
            }

            Hashtable alreadyLoaded = new Hashtable();
            foreach (string name in args)
            {
                Assembly assm = Assembly.LoadFrom(name);
                DumpAssembly(assm, alreadyLoaded, 0);
            }
        }
        catch (Exception e)
        {
            DumpError(e);
        }

        Console.WriteLine("\nPress any key to continue...");
        Console.ReadKey();
    }

    static void DumpAssembly(Assembly assm, Hashtable alreadyLoaded, int indent)
    {
        Console.Write(new String(' ', indent));
        AssemblyName fqn = assm.GetName();
        if (alreadyLoaded.Contains(fqn.FullName))
        {
            Console.WriteLine("[{0}:{1}]", fqn.Name, fqn.Version);
            return;
        }
        alreadyLoaded[fqn.FullName] = fqn.FullName;
        Console.WriteLine(fqn.Name + ":" + fqn.Version);

        foreach (AssemblyName name in assm.GetReferencedAssemblies())
        {
            try
            {
                Assembly referenced = Assembly.Load(name);
                DumpAssembly(referenced, alreadyLoaded, indent + 2);
            }
            catch (Exception e)
            {
                DumpError(e);
            }
        }
    }

    static void DumpError(Exception e)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine("Error: {0}", e.Message);
        Console.WriteLine();
        Console.ResetColor();
    }
}
KyleMit
  • 30,350
  • 66
  • 462
  • 664
Presidenten
  • 6,327
  • 11
  • 45
  • 55
  • 2
    This code won't show unmanaged modules. Mono.Cecil would be a much better solution for managed code because it doesn't require you to load assemblies into AppDomain (and you can't unload assembly later) – aku Jan 16 '09 at 14:48
  • Added extra try/catch, if one assembly fails, the others should be listed. Added a color to the exception and an enter so it's easier to read. Added a string field for when you only want to run an F5 for a quick overview (is easier than adding it to the build settings). – Kees C. Bakker Nov 05 '13 at 11:19
1

While this question already has an accepted answer, the documentation referenced in the other answers, where not broken, is old. Rather than reading through all of it only to find it doesn't cover differences between Win32 and x64, or other differences, my approach was this:

C:\UnxUtils\usr\local\wbin>strings.exe E:\the-directory-I-wanted-the-info-from\*.dll > E:\TEMP\dll_strings.txt

This allowed me to use Notepad++ or gvim or whatever to search for dlls that were still depending on MS dlls with 120.dll at the end of the dll name so I could find the ones that needed updating.

This could easily be scripted in your favorite language.

Given that my search for this info was with VS 2015 in mind, and this question was the top result for a Google search, I supply this answer that it may perhaps be of use to someone else who comes along looking for the same thing.

hlongmore
  • 1,603
  • 24
  • 28
1

To get native module dependencies, I believe it should be ok to get it from the PE file's import table, here are 2 links which explain that in-depth:

http://msdn.microsoft.com/en-us/magazine/bb985992.aspx

http://msdn.microsoft.com/en-us/magazine/cc301808.aspx

To get .NET dependencies, we can use .NET's API, like Assembly.Load.

To get a .NET module's all dependencies, How about combine the 2 ways - .NET assemblies are just PE file with meta data.

Baiyan Huang
  • 6,463
  • 8
  • 45
  • 72
0

If you don't want to load the assembly in your program, you can use DnSpy (https://www.nuget.org/packages/dnSpyLibs):

var assemblyDef = dnlib.DotNet.AssemblyDef.Load("yourDllName.dll");
var dependencies = assemblyDef.ManifestModule.GetAssemblyRefs();

Notice that you have all the infos you can want in the "ManifestModule" property.

  • This is a great start... now to just figure out how to have it walk the entire tree (ie getting to thge actual assembly file for the dependency to load that... – David V. Corbin Nov 03 '22 at 12:54
0

To read the DLL's (modules) loaded by a running exe, use the ToolHelp32 functions Tool help Documentation on MSDN.

Not sure what it will show for a .Net running exe (I've never tried it). But, it does show the full path from where the DLL's were loaded. Often, this was the information I needed when trying to sort out DLL problems. .Net is supposed to have removed the need to use these functions (look up DLL Hell for more information).

Aussie Craig
  • 772
  • 4
  • 5