如何确定 .NET 应用程序的依赖关系?Dependency Walker是否适用于托管应用程序?我已经下载了最新版本并尝试分析该应用程序,但它只是退出而没有太多解释。如果它不适用于 .NET,那么是否有其他工具可以帮助我调试运行时 DLL 加载问题?
14 回答
Dependency walker 适用于普通的 win32 二进制文件。所有 .NET dll 和 exe 都有一个小的 stub 标头部分,这使它们看起来像普通的二进制文件,但它基本上所说的只是“加载 CLR”——这就是依赖 walker 会告诉你的全部内容。
要查看您的 .NET 应用程序实际依赖的东西,您可以使用Red Gate非常出色的.NET 反射器。(编辑:请注意,.NET Reflector 现在是付费产品。ILSpy是免费和开源的,非常相似。)
将您的 DLL 加载到其中,右键单击并选择“分析” - 然后您将看到一个“取决于”项目,它将向您显示它需要的所有其他 dll(以及这些 dll 中的方法)。
但有时它会变得更棘手,因为您的应用程序依赖于 X dll,并且存在 X dll,但无论出于何种原因,都无法在运行时加载或定位。
为了解决这些问题,Microsoft 有一个程序集绑定日志查看器,它可以显示运行时发生的情况
我发现小型实用程序AsmSpy是解决加载程序集问题的宝贵工具。它列出了托管程序集的所有程序集引用,包括程序集版本。
.dll
使用以下参数在 目录中的命令提示符下运行它:
asmspy . all
使用 Chocolatey 快速安装:
choco install asmspy
在 ILDASM 中打开程序集文件并查看 MANIFEST 中的 @ .assembly extern
您无需下载和安装共享软件应用程序或工具。您可以使用 .NET 以编程方式执行此操作Assembly.GetReferencedAssemblies()
Assembly.LoadFile(@"app").GetReferencedAssemblies()
要浏览 .NET 代码依赖项,您可以使用工具 NDepend 的功能。该工具建议:
- 依赖图
- 一个依赖矩阵,
- 并且还可以编辑(或生成)一些C# LINQ 查询以浏览依赖项。
例如,此类查询可能如下所示:
from m in Methods
let depth = m.DepthOfIsUsing("NHibernate.NHibernateUtil.Entity(Type)")
where depth >= 0 && m.IsUsing("System.IDisposable")
orderby depth
select new { m, depth }
其结果如下所示:(注意代码度量depth,1 用于直接调用者,2 用于直接调用者的调用者...)(还要注意 Export to Graph 按钮将查询结果导出到Call Graph)
依赖图如下所示:
依赖矩阵如下所示:
依赖矩阵实际上不如图表直观,但它更适合浏览复杂的代码部分,例如:
免责声明:我为 NDepend 工作
如果您使用的是 Mono 工具链,则可以使用带有参数的monodis
实用程序--assemblyref
来列出 .NET 程序集的依赖项。这将适用于.exe
和.dll
文件。
示例用法:
monodis --assemblyref somefile.exe
示例输出(.exe):
$ monodis --assemblyref monop.exe
AssemblyRef Table
1: Version=4.0.0.0
Name=System
Flags=0x00000000
Public Key:
0x00000000: B7 7A 5C 56 19 34 E0 89
2: Version=4.0.0.0
Name=mscorlib
Flags=0x00000000
Public Key:
0x00000000: B7 7A 5C 56 19 34 E0 89
示例输出(.dll):
$ monodis --assemblyref Mono.CSharp.dll
AssemblyRef Table
1: Version=4.0.0.0
Name=mscorlib
Flags=0x00000000
Public Key:
0x00000000: B7 7A 5C 56 19 34 E0 89
2: Version=4.0.0.0
Name=System.Core
Flags=0x00000000
Public Key:
0x00000000: B7 7A 5C 56 19 34 E0 89
3: Version=4.0.0.0
Name=System
Flags=0x00000000
Public Key:
0x00000000: B7 7A 5C 56 19 34 E0 89
4: Version=4.0.0.0
Name=System.Xml
Flags=0x00000000
Public Key:
0x00000000: B7 7A 5C 56 19 34 E0 89
启用程序集绑定日志将 HKLM\Software\Microsoft\Fusion 中的注册表值 EnableLog 设置为 1。请注意,您必须重新启动应用程序(使用 iisreset)才能使更改生效。
提示:请记住在完成后关闭融合日志记录,因为打开它会降低性能。
有趣的是,我遇到了类似的问题,但没有找到任何合适的东西,并且知道旧的 Dependency Walker,所以最后我自己写了一个。
这专门处理 .NET 并将递归地显示程序集具有(和缺少)的引用。它还将显示本机库依赖项。
它是免费的(供个人使用),任何有兴趣的人都可以在这里获得:www.netdepends.com
欢迎反馈。
ChkAsm 将一次显示特定程序集的所有依赖项,包括版本,并轻松让您在列表中搜索程序集。为此目的比 ILSpy ( http://ilspy.net/ ) 好得多,这是我用来完成此任务的工具。
我使用的另一个方便的反射器插件是依赖结构矩阵。看到什么类使用什么真是太好了。另外它是免费的。
尝试使用选项编译您的 .NET 程序集--staticlink:"Namespace.Assembly"
。这会强制编译器在编译时引入所有依赖项。如果遇到未引用的依赖项,它将给出警告或错误消息,通常带有该程序集的名称。
Namespace.Assembly
是您怀疑存在依赖性问题的程序集。通常,仅静态链接此程序集将传递引用所有依赖项。
为更新的 .Net 版本提供解决方案
当 OP 提出问题时,情况可能并非如此,但目前有一个内置dotnet
命令用于列出解决方案中的包依赖项:
PS C:\foo> dotnet list package
Project 'foo' has the following package references
[net5.0]:
Top-level Package Requested Resolved
... ... ...
可以在 Microsoft 文档网站上找到更多信息:https ://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-list-package
在我的公司,我们使用 Ashutosh Bhawasinka 的“装配信息”。它被实现为一个外壳扩展,因此您只需右键单击 *.dll 文件即可获得信息。您可以查看依赖关系树或获取所有依赖关系的平面列表。我喜欢这个工具的地方在于它还显示了公钥令牌,这是检查冲突的好方法。这是我公司的一个程序集的平面列表输出示例:
ICSharpCode.SharpZipLib, Version=0.86.0.518, Culture=neutral, PublicKeyToken=484f84ea1d6cf4da
mscorlib, Culture=neutral, PublicKeyToken=b77a5c561934e089
mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
我们在 .Net Framework 4.0 中编译,因此您可以在 mscorlib 上看到该版本;我们还引用了为 .Net Framework 2.0 编译的 SharpZipLib,因此我们也看到了这种依赖关系。好的。
唯一的问题是该实用程序发布在已关闭的 CodePlex 上。幸运的是,我们保留了原始文件的副本。我在网络上的其他任何地方都找不到它,所以我决定在这里发布它供任何人获取(看起来我们只保存了 64 位版本):
http://riosoftware.com/temp/pub/Assembly%20Information%20for%2064bit%20Operating%20System.zip
如果您发现此链接和工具有用,请“投票”此答案以帮助他人!
我看到和使用的最佳应用程序,显示错过/有问题的 dll: http: //www.dependencywalker.com/