找出所有 DLL 的依赖关系?

Posted

技术标签:

【中文标题】找出所有 DLL 的依赖关系?【英文标题】:Find out dependencies of all DLLs? 【发布时间】:2013-02-13 08:01:43 【问题描述】:

我有一组 DLL(比如 20 个)。如何找出某个特定 DLL(比如 DLL A)所依赖的所有 DLL?

【问题讨论】:

【参考方案1】:

如果您指的是编程方式,请使用Assembly.GetReferencedAssemblies

您可以递归地使用它来查找您需要的所有程序集。 (所以你找到X的依赖,然后是依赖的依赖等等)

【讨论】:

您需要包含“使用 System.Reflection;” @greenfeet:不一定——例如,您可以使用var assemblies = typeof(Foo).Assembly.GetReferencedAssemblies();。通常,不值得添加答案中引用的所有类型使用的所有命名空间 - 特别是当存在指向相关类型的链接时。我假设读者足够了解 C# 语言,知道何时添加 using 指令。 @theoski:使用指令只是意味着你不必完全限定名称......我真的不明白你在问什么。 @kayleeFrye_onDeck:鉴于它已被接受并且没有提供其他信息,我认为假设它关于 .NET 程序集是合理的。 我知道这可能是意图,@JonSkeet,但是当我遇到这个问题时,我正在寻找关于 DLL 的不太具体的内容,问题的描述,它的标签,以及缺乏提及程序集与通用 DLL 可能会引起混淆。我不是在质疑您对 OP 的回答的有效性。【参考方案2】:

由于问题被标记为“C#”,我假设您在谈论托管 dll(程序集)。在这种情况下,dependencywalker 没有用。如果你想用一个程序来做到这一点,JetBrians 的 dotPeek 和 RedGate 的 Reflector 是不错的选择。或者您甚至可以使用 Visual Studio 中的对象检查器。

但是,这可能是一个漫长的过程,也很麻烦。正如 Jon 所说,我会编写一个使用 Assembly.GetReferencedAssemblies 的简短 C# 程序/F# 脚本。

如果您想检查程序(C# 代码)的本地 DLL 依赖关系,则必须检查 PE 文件(MS dll 和 exe 文件格式)及其 IAT(导入地址表)。不容易,但也不是不可能……

我会开始 here on MSDN 和 here 来理解 PE 部分,并使用托管库来阅读它(有很多,包括 Mono 项目中的一些(我在想 Cecil,它应该可以工作也可以使用原生二进制文件);过去我使用过来自优秀的 John Gough 的 this one。

【讨论】:

【参考方案3】:

您可以使用dependency walker http://www.dependencywalker.com 来解决这个问题。请注意 x32 和 x64 之间的区别。

Dependency Walker 是一个免费实用程序,可以扫描任何 32 位或 64 位 Windows 模块(exe、dll、ocx、sys 等)并构建分层 所有依赖模块的树形图。

【讨论】:

【参考方案4】:

所有答案归功于以前的作者使用Assembly.GetReferencedAssemblies。这只是一个只适用于 .NET 程序集的即写即忘 C# 控制台应用程序。 return 0 在您能够检查的程序集上,成功后将它们输出到 STDOUT。其他一切都会return 1 并打印某种错误输出。你可以抓住要点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;
        
    

用法:

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

输出:

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

【讨论】:

【参考方案5】:

对于 .NET 程序集,查看程序集所依赖的程序集的绝佳工具是 AsmSpy。

【讨论】:

它没有列出间接程序集。【参考方案6】:

如果您需要 DLL(文件),Assembly.GetReferencedAssemblies 也将返回 .Net Framework 程序集。

这是一个简单的代码 sn-p,它将获取它可以在当前目录中找到的 dll(还包括一些其他相关文件):

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

你可以这样称呼它:MessageBox.Show(string.Join("\r\n", GetDependentFiles(Assembly.GetEntryAssembly())));

【讨论】:

以上是关于找出所有 DLL 的依赖关系?的主要内容,如果未能解决你的问题,请参考以下文章

Microsoft Visual C++ - 编译一个没有依赖关系的单个 DLL

如何找出哪个 gem 具有特定的依赖关系?

由于未解决的依赖关系,无法使用 Winforms 控件

找出关系中的函数依赖

最终编译的程序集中.Net中项目和dll依赖关系的区别

未复制到输出目录的引用的依赖关系