English 中文(简体)
如何编程获取DLL依赖关系
原标题:
  • 时间:2009-01-16 10:44:18
  •  标签:

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

换句话说,我想以编程的方式执行与“依赖项侦测器”工具相同的操作。

这个有没有Windows(最好是.NET)的API?

最佳回答

你可以使用EnumProcessModules函数。像kaanbardak建议的托管API不会给你一个本地模块的列表。

例如,请参见MSDN上的此页面

如果您需要静态分析您的DLL文件,您必须深入了解PE格式并学习有关导入表的知识。请查阅优秀的教程以获取详细信息。

问题回答

注意:根据下面帖子里的评论,我认为这个方法可能会忽略未管理的依赖项,因为它依赖反射。

这是一个由Jon Skeet在bytes.com上编写的小型C#程序,关于.NET依赖项浏览程序。

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

为获取本地模块依赖项,我认为从PE文件的导入表中获取应该是可以的,以下是两个深入解释此事的链接:

将此翻译成中文:http://msdn.microsoft.com/en-us/magazine/bb985992.aspx http://msdn.microsoft.com/en-us/magazine/bb985992.aspx

将此翻译为中文:http://msdn.microsoft.com/en-us/magazine/cc301808.aspx http://msdn.microsoft.com/en-us/magazine/cc301808.aspx

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

如何获取 .NET 模块的所有依赖项?可以将两种方式结合起来——.NET 程序集只是带有元数据的 PE 文件。

尽管这个问题已经有了一个被接受的回答,但其他答案中引用的文档如果没有损坏,就是过时的。与其阅读全部内容,仅仅发现它没有涵盖Win32和x64之间的差异或其他差异,我的方法是:

C:UnxUtilsusrlocalwbin>strings.exe E:	he-directory-I-wanted-the-info-from*.dll > E:TEMPdll_strings.txt

这使我可以使用Notepad ++或gvim或其他工具搜索仍然依赖于以120.dll结尾的MS dlls的dll,以便我找到需要更新的dll。

这很容易在你喜欢的编程语言中编写。

鉴于我的搜索是基于VS 2015的,而这个问题是通过谷歌搜索得到的最佳结果,我提供这个答案,希望它对其他寻找同样信息的人有所帮助。

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

不确定 .Net 运行的 exe 会显示什么(我从来没有尝试过)。但是,它确实显示了从哪里加载了 DLL 的完整路径。通常,当我尝试解决 DLL 问题时,这就是我需要的信息。.Net 据说已经消除了使用这些功能的必要性(查阅 DLL 地狱以获取更多信息)。

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

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

请注意,您可以在“ManifestModule”属性中获取所有您想要的信息。





相关问题
热门标签