【发布时间】:2010-09-18 16:17:06
【问题描述】:
如何确定 .NET 应用程序的依赖关系? Dependency Walker 是否适用于托管应用程序?我已经下载了最新版本并尝试分析该应用程序,但它只是退出而没有太多解释。如果它不适用于 .NET,那么是否有其他工具可以帮助我调试运行时 DLL 加载问题?
【问题讨论】:
标签: .net dll dependencies dependency-walker
如何确定 .NET 应用程序的依赖关系? Dependency Walker 是否适用于托管应用程序?我已经下载了最新版本并尝试分析该应用程序,但它只是退出而没有太多解释。如果它不适用于 .NET,那么是否有其他工具可以帮助我调试运行时 DLL 加载问题?
【问题讨论】:
标签: .net dll dependencies dependency-walker
Dependency walker 适用于普通的 win32 二进制文件。所有 .NET dll 和 exe 都有一个小的 stub 标头部分,这使它们看起来像普通的二进制文件,但它基本上说的是“加载 CLR”——这就是依赖分析程序会告诉你的全部内容。
要查看您的 .NET 应用程序实际依赖的东西,您可以使用 Red Gate 提供的非常出色的 .NET reflector。 (编辑:请注意,.NET Reflector 现在是付费产品。ILSpy 是免费和开源的,非常相似。)
将您的 DLL 加载到其中,单击鼠标右键,然后选择“分析” - 然后您会看到一个“取决于”项,它将向您显示它需要的所有其他 dll(以及这些 dll 中的方法)。
但有时它会变得更棘手,因为您的应用依赖于 X dll,并且存在 X dll,但由于某种原因无法在运行时加载或定位。
为了解决这类问题,Microsoft 提供了一个Assembly Binding Log Viewer,它可以向您显示运行时发生的情况
【讨论】:
启用程序集绑定日志将 HKLM\Software\Microsoft\Fusion 中的注册表值 EnableLog 设置为 1。请注意,您必须重新启动应用程序(使用 iisreset)才能使更改生效。
提示:请记住在完成后关闭融合日志记录,因为打开它会降低性能。
【讨论】:
要浏览 .NET 代码依赖项,您可以使用工具 NDepend 的功能。该工具提出:
例如,这样的查询可能如下所示:
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 用于直接调用者的调用者...)(另请注意导出到图形按钮以导出查询结果到Call Graph)
依赖图如下:
依赖矩阵如下:
依赖矩阵事实上不如图表直观,但它更适合浏览复杂的代码部分,例如:
免责声明:我为 NDepend 工作
【讨论】:
我使用的另一个方便的反射器插件是Dependency Structure Matrix。看到什么类使用什么真是太好了。而且它是免费的。
【讨论】:
在 ILDASM 中打开程序集文件并查看 MANIFEST 中的 @.assembly extern
【讨论】:
如果您使用 Mono 工具链,您可以使用 the monodis utility 和 --assemblyref 参数来列出 .NET 程序集的依赖项。这将适用于 .exe 和 .dll 文件。
monodis --assemblyref somefile.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
$ 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
【讨论】:
ChkAsm 将一次显示特定程序集的所有依赖项,包括版本,并让您轻松搜索列表中的程序集。 在此目的上比 ILSpy (http://ilspy.net/) 效果更好,这是我用来完成此任务的工具。
【讨论】:
我看到和使用的最佳应用程序,显示丢失/有问题的 dll: http://www.dependencywalker.com/
【讨论】:
您无需下载和安装共享软件应用程序或工具。您可以使用 Assembly.GetReferencedAssemblies() 以编程方式从 .NET 执行此操作
Assembly.LoadFile(@"app").GetReferencedAssemblies()
【讨论】:
[Reflection.Assembly]::LoadFile('C:\absolute\path\to\my.dll').GetReferencedAssemblies()。具有不为工具下载或寻找晦涩的 Windows 位置的好处。 +1
有趣的是,我遇到了类似的问题,但没有找到任何合适的东西,并且知道旧的 Dependency Walker,所以最后我自己写了一个。
这专门处理 .NET,并将递归地显示程序集具有(和缺少)的引用。它还将显示本机库依赖项。
它是免费的(供个人使用),任何感兴趣的人都可以在这里获得:www.netdepends.com
欢迎反馈。
【讨论】:
我发现小型实用程序AsmSpy 是解决加载程序集问题的宝贵工具。它列出了托管程序集的所有程序集引用,包括程序集版本。
在.dll 目录中的命令提示符下使用以下参数运行它:
asmspy . all
使用 Chocolatey 快速安装:
choco install asmspy
【讨论】:
尝试使用选项 --staticlink:"Namespace.Assembly" 编译您的 .NET 程序集。这会强制编译器在编译时引入所有依赖项。如果遇到未引用的依赖项,它将给出警告或错误消息,通常带有该程序集的名称。
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
... ... ...
更多信息可以在微软文档网站上找到: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
如果您发现此链接和工具有用,请“支持”此答案以帮助他人!
【讨论】: