用 Dependencies 快速定位 Windows DLL 加载问题
【免费下载链接】DependenciesA rewrite of the old legacy software "depends.exe" in C# for Windows devs to troubleshoot dll load dependencies issues.项目地址: https://gitcode.com/gh_mirrors/de/Dependencies
Windows 程序报“找不到模块 xxx.dll”时,光看报错很难判断断在依赖链哪一环。Dependencies 是开源的 Windows 依赖分析工具,命令行版Dependencies.exe能递归导出完整依赖树和函数级导入/导出表,并支持 JSON 输出;GUI 版适合交互式排查。需要定位 DLL 加载问题的 Windows 开发者和写 CI 脚本的自动化工程师,都可以用它。
为什么需要一个新的依赖分析工具
随 Windows SDK 分发的 depends.exe(Dependency Walker)早已停止维护,对现代 Windows 支持不佳:ApiSet 重定向、x86/x64 混合环境这些新机制基本覆盖不到。Dependencies 用 C# 重写了解析层,CLI 与 GUI 共用同一套核心 PE 解析逻辑(ClrPhlib/src/unmanaged/UnmanagedPE.cpp),自动化场景走 CLI,交互式排查用 GUI。
三十秒上手 Dependencies.exe
两种获取方式:
- 源码构建:用
Dependencies.sln打开解决方案,手动选择Release配置和x64平台(默认值可能不是这两个)。 - 下载发布包:从 Releases 页面下载压缩包,解压即用。
⚠️ 两个前提:受 /clr 编译限制,机器上需安装 Visual C++ Redistributable;二进制未签名,首次运行 SmartScreen 可能弹警告,属正常现象。
最简命令形式如下,不带参数或加-help会打印完整帮助:
Dependencies.exe [OPTIONS] <FILE> Dependencies.exe -helpWindows DLL 排查的四个实战场景
场景一:如何导出完整依赖树,找到失踪的 DLL
运行时报“找不到 DLL”,先拿完整依赖树:
Dependencies.exe -chain MyApp.exe Dependencies.exe -chain -depth 2 MyApp.exe-chain递归解析目标的所有 DLL 依赖,每个节点标注模块搜索策略——即这个 DLL 从哪儿找到的:ROOT、ApiSetSchema、WellKnownDlls、System32Folder、Environment等,完整枚举见 DependenciesLib/FindPeModule.cs,对应 NT Loader 的查找顺序。输出里标NOT_FOUND的节点,就是失踪的 DLL。树太深时用-depth N限制递归深度,默认不限制。
不要树结构时,-modules只输出已解析模块的扁平清单;-sxsentries列出文件的 SxS 依赖项,解析不到路径的标???。
场景二:如何转储导入导出表,排查函数级依赖
DLL 能加载、却报找不到入口点或函数缺失时,要看函数级细节:
Dependencies.exe -imports MyApp.exe Dependencies.exe -exports kernel32.dll-imports按模块分组列出导入函数,兼容按名字和按序数(Ordinal_xxx)两种导入,延迟加载项标Delay Import——这类 DLL 运行时才加载,是常见坑点。-exports给出每个导出的名称、序数与虚拟地址,转发导出(ForwardedName)同样可见。
.NET 程序另有-assemblyrefs(列出程序集引用并尝试本地解析版本号)和-modulerefs(列出模块引用)两个开关。-manifest转储内嵌 SxS 清单(XML 格式),仓库回归脚本 test/manifest-regress/Test-ManifestRegress.ps1 就是用它验证清单解析的。
场景三:如何查看 ApiSet 重定向表与 KnownDlls 白名单
这类开关无需目标文件,直接查系统环境:
Dependencies.exe -apisets Dependencies.exe -knowndll Dependencies.exe -apisetsdll test/apisetschema.v6.dllApiSet 重定向是 Windows 8.1+ 的重要机制:大量api-ms-win-*.dll只是别名,实际由宿主 DLL 承载,“找不到 api-ms-win-*”的报错根源多半在这张表里,-apisets可直接转储。-knowndll列出 x86 与 x64 两套 KnownDlls 白名单,能解释“为什么加载了 System32 里那个同名 DLL”。-apisetsdll从指定的 apisetschema 文件转储,test 目录的apisetschema.v6.dll可当测试素材。
场景四:把依赖分析接进 CI 流水线
多数命令支持-json开关,把结果输出为缩进 JSON(序列化实现在 Dependencies/Program.cs):
Dependencies.exe -json -chain MyApp.exe > deps.json Dependencies.exe -json -imports MyApp.exe | jq '.Imports[0]'CI 里三种常见用法:
- 依赖变更检测:每次构建导出 JSON 快照,与基线 diff,依赖集有变化能及时发现。
- 缺失断言:脚本解析 JSON,出现
SearchStrategy: "NOT_FOUND"节点就让流水线失败。 - 报告归档:把
deps.json作为构建产物存档,事后排查有据可查。
PowerShell 可直接ConvertFrom-Json消费输出。
⚠️ 注意:-modules目前不支持 JSON 输出(会提示 "Json output is not currently supported"),需要机器可读结果时改用-chain或-imports。appveyor.yml 展示了 x86/x64 双平台构建流程,Deploy-Dependencies.ps1在构建后执行自动化验证,可作流水线参考。
常用命令速查
| 场景 | 命令示例 | 是否需目标文件 | 输出可否脚本化 |
|---|---|---|---|
| 递归导出依赖树 | -chain MyApp.exe | 是 | 可(-json) |
| 限制递归深度 | -chain -depth 2 MyApp.exe | 是 | 可(-json) |
| 扁平模块清单 | -modules MyApp.exe | 是 | 不可 |
| 导入表(函数级) | -imports MyApp.exe | 是 | 可(-json) |
| 导出表(函数级) | -exports kernel32.dll | 是 | 可(-json) |
| .NET 程序集引用 | -assemblyrefs MyApp.exe | 是 | 可(-json) |
| 内嵌 SxS 清单 | -manifest MyApp.exe | 是 | 可(-json) |
| 系统 ApiSet 表 | -apisets | 否 | 可(-json) |
| KnownDlls 白名单 | -knowndll | 否 | 可(-json) |
| 启用二进制缓存 | -cache MyApp.exe(可与其他开关组合) | 否 | — |
-cache开启二进制缓存:读取时先复制一份文件,避免 DLL 被锁定,适合批量解析场景。
对排查 DLL 加载问题的 Windows 开发者、做依赖回归的自动化工程师来说,Dependencies 命令行版是现成的开源方案,装上就能用。
【免费下载链接】DependenciesA rewrite of the old legacy software "depends.exe" in C# for Windows devs to troubleshoot dll load dependencies issues.项目地址: https://gitcode.com/gh_mirrors/de/Dependencies
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考