如何以编程方式获取DLL依赖项

时间:2009-01-16 10:44:19

标签: dll dependencies

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

换句话说,我想和“Dependency walker”工具一样,但是以编程方式。

什么是Windows(理想情况下是.NET)API?

6 个答案:

答案 0 :(得分:11)

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

例如,请参阅MSDN上的this page

如果你需要静态分析你的dll,你必须深入研究PE format并了解导入表。有关详细信息,请参阅此excellent tutorial

答案 1 :(得分:4)

  

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

这是一个由来自bytes.com的Jon Skeet在.NET Dependency Walker上编写的小型c#程序

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();
    }
}

答案 2 :(得分: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文件。

答案 3 :(得分: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或其他任何东西来搜索仍然依赖于带有120.dll的dll名称末尾的MS dll的dll,这样我就能找到需要更新的那些。

这可以用您最喜欢的语言轻松编写脚本。

鉴于我对这个信息的搜索是考虑到VS 2015,而这个问题是Google搜索的最佳结果,我提供的答案可能对其他人来说也许有用。的事情。

答案 4 :(得分:0)

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

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

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

答案 5 :(得分:-1)

要读取正在运行的exe加载的DLL(模块),请使用ToolHelp32函数 Tool help Documentation on MSDN

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