19

如何获取给定 DLL 或 EXE 文件的所有 DLL 依赖项的列表?

换句话说,我想以编程方式执行与“Dependency walker”工具相同的操作。

什么是 Windows(最好是 .NET)API?

4

6 回答 6

13

您可以使用EnumProcessModules函数。kaanbardak 建议的托管 API 不会为您提供本机模块列表。

例如在 MSDN 上看到这个页面

如果您需要静态分析您的 dll,您必须深入研究PE 格式并了解导入表。有关详细信息,请参阅此出色的教程

于 2009-01-16T10:52:20.097 回答
4

注意:根据下面帖子的评论,我想这也可能会错过非托管依赖项,因为它依赖于反射。

这是一个小的 c# 程序,由来自 bytes.com 的 Jon Skeet 在.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();
    }
}
于 2009-01-16T13:45:00.977 回答
1

要获取本机模块依赖项,我认为从 PE 文件的导入表中获取它应该是可以的,这里有 2 个链接可以深入解释这一点:

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

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

要获取 .NET 依赖项,我们可以使用 .NET 的 API,例如 Assembly.Load。

要获得 .NET 模块的所有依赖项,如何结合两种方式 - .NET 程序集只是带有元数据的 PE 文件。

于 2009-03-10T08:32:38.177 回答
1

虽然这个问题已经有一个公认的答案,但其他答案中引用的文档(如果没有损坏)是旧的。我没有通读所有内容,只是发现它没有涵盖 Win32 和 x64 之间的差异或其他差异,我的方法是:

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

这允许我使用 Notepad++ 或 gvim 或其他任何东西来搜索仍然依赖于 dll 名称末尾带有 120.dll 的 MS dll 的 dll,这样我就可以找到需要更新的那些。

这可以很容易地用您喜欢的语言编写脚本。

鉴于我在搜索此信息时考虑了 VS 2015,并且此问题是 Google 搜索的最高结果,因此我提供此答案可能对寻找相同内容的其他人有用。

于 2016-02-05T23:01:11.760 回答
0

要读取正在运行的 exe 加载的 DLL(模块),请使用 MSDN 上的 ToolHelp32 函数工具帮助文档

不知道运行 .Net 的 exe 会显示什么(我从未尝试过)。但是,它确实显示了加载 DLL 的完整路径。通常,这是我在尝试解决 DLL 问题时需要的信息。.Net 应该已经消除了使用这些函数的需要(查找 DLL Hell 以获取更多信息)。

于 2009-03-10T09:44:34.650 回答
0

如果您不想在程序中加载程序集,可以使用 DnSpy ( https://www.nuget.org/packages/dnSpyLibs ):

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

请注意,您在“ManifestModule”属性中拥有所需的所有信息。

于 2019-03-08T17:43:27.037 回答