一次讲透 Dependencies 命令行:从依赖树到 JSON 接入 CI 流水线实战
【免费下载链接】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
用户机器上弹出提示:"xxx.dll 找不到,代码执行无法继续"。开发机复现不了,翻遍那个 DLL 的名字也没有头绪。Dependencies 命令行版(Dependencies.exe)是老 depends.exe 的现代替代:一条命令导出完整依赖链,一条命令转储导入表,-json输出还能直接接进 CI 流水线。
下面是按"三步排查 + 自动化固化"组织的实战流程,最后附全参数速查。
工具定位与获取:Dependencies.exe 两种拿到手的方式
Dependencies 是对随 Windows SDK 分发的遗留工具 depends.exe(Dependency Walker)的 C# 重写。它提供两个可执行文件:GUI 版DependenciesGui.exe负责交互式排查,CLI 版Dependencies.exe负责自动化。两者共用同一套 PE 解析引擎(PE 即可移植执行文件,Windows 下 .exe/.dll 的二进制格式),核心解析逻辑位于 ClrPhlib/src/unmanaged/UnmanagedPE.cpp,所以命令行版的分析结果可以直接作为排查依据。
获取方式只有两种:
- 下载发布包:从 Releases 页取 zip 解压即用,无需安装器。
- 源码构建:
git clone https://gitcode.com/gh_mirrors/de/Dependencies打开 Dependencies.sln 后注意手动选择 Release 配置与 x64 平台(默认值未必是这两个),再执行构建。
⚠️ 受 /clr 混合编译限制,运行前需安装 Visual C++ Redistributable;二进制未签名,首次运行触发 SmartScreen 警告属正常现象。
命令基本形态:
Dependencies.exe [OPTIONS] <FILE>不带参数或加-help打印完整帮助。
排查第一步:如何用 -chain 依赖树找到缺失 DLL
先给结论:树里的NOT_FOUND节点,就是你要找的"失踪 DLL"。
Dependencies.exe -chain MyApp.exe输出是一棵递归树,每个节点标注它的搜索策略——即 NT Loader 查找 DLL 的顺序中,它是从哪一步被命中的:
ROOT:命令行传入的文件本身;ApiSetSchema:经 ApiSet 重定向表命中(机制见第三步);WellKnownDlls:命中 KnownDlls 系统白名单——该名单会强制部分 DLL 一律从 System32 加载;System32Folder/WindowsFolder:在 C:\Windows\System32 或 C:\Windows 中找到;Environment:通过 PATH 环境变量找到;NOT_FOUND:哪里都没找到。
完整策略枚举见 DependenciesLib/FindPeModule.cs。树太深时用-depth限制递归(默认无限):
Dependencies.exe -chain -depth 2 MyApp.exe两个配套命令:
-modules:只列已解析模块的扁平清单(无树结构),适合快速核对"最终会加载哪些 DLL";-sxsentries:列出文件的 SxS(Side-by-Side 程序集,Windows 侧边组件机制)依赖项,路径解析不到的条目标注???。
排查第二步:-imports 与 -exports 导入导出表做函数级定位
DLL 能加载但缺函数、或版本不对,就要看函数级信息。
转储导入表:它需要哪些函数
Dependencies.exe -imports MyApp.exe按模块分组列出每个导入函数。注意两个细节:
- 序数导入:无函数名的项显示为
Ordinal_xxx,表示按序数(数字编号)而非按名字导入; - 延迟加载:标注
Delay Import的项,对应 DLL 只在运行时首次调用该函数时才被加载——延迟加载 DLL 缺失时,程序启动正常、触发功能才崩,是最难查的一类问题。
转储导出表:它提供哪些函数
Dependencies.exe -exports kernel32.dll列出每个导出的名称、序数与虚拟地址(VA);转发导出会额外给出ForwardedName,指向真正函数所在的模块。
.NET 程序的两个专属开关
Dependencies.exe -assemblyrefs MyApp.exe Dependencies.exe -modulerefs MyApp.exe前者列出程序集引用并尝试本地解析出具体版本,后者列出原生模块引用。
内嵌清单:-manifest
Dependencies.exe -manifest MyApp.exe转储文件内嵌的 SxS 清单(XML)。项目自带的清单回归测试脚本 test/manifest-regress/Test-ManifestRegress.ps1 正是用这个开关验证解析结果、防止回归的。
排查第三步:-apisets 与 -knowndll 验证系统机制
很多"找不到 api-ms-win-*.dll"的报错,缺的不是文件,而是没看懂重定向机制。
ApiSet是 Windows 8.1 引入的重定向表:api-ms-win-core-*.dll这类虚拟 DLL 名在磁盘上并不存在实体文件,而是通过这张表映射到真实的系统 DLL。三条验证命令:
Dependencies.exe -apisets Dependencies.exe -apisetsdll test/apisetschema.v6.dll Dependencies.exe -knowndll-apisets:转储当前系统的 ApiSet 重定向表,一条命令即可确认 api-ms-win-* 报错的"根源"在哪;-apisetsdll:从指定的apisetschema.dll文件读表,仓库test/apisetschema.v6.dll可直接当素材,方便对照不同系统版本;-knowndll:列出系统 KnownDlls 白名单(x86 与 x64 两份),解释"为什么加载了 System32 里那个同名 DLL"。
另外,若分析动作锁住了 DLL 文件、妨碍程序更新,加-cache:二进制缓存在读取时复制文件,避免文件锁定。
Dependencies JSON 输出接 CI 流水线的 3 种写法
大多数命令加-json即输出缩进 JSON,脚本可直接消费:
Dependencies.exe -json -chain MyApp.exe > deps.json三种玩法:
- 依赖基线 diff:每次构建后导出依赖快照,与基线做 diff,依赖集悄悄变化就能被逮住;
- 缺失 DLL 断言:解析 JSON,出现
SearchStrategy: "NOT_FOUND"节点即让流水线失败。PowerShell 用ConvertFrom-Json直接消费,无需额外依赖:
$deps = & Dependencies.exe -json -chain MyApp.exe | ConvertFrom-Json function Get-MissingNode { param($node) if ($node.SearchStrategy -eq "NOT_FOUND") { $node } $node.Dependencies | ForEach-Object { Get-MissingNode $_ } } if (Get-MissingNode $deps) { throw "存在缺失依赖,流水线失败" }- 报告归档:把
deps.json作为构建产物归档,事后排查有据可查。
📌 注意:
-modules目前不支持 JSON 输出(直接运行会提示 "Json output is not currently supported"),自动化脚本请改用-chain或-imports。
仓库的 appveyor.yml 跑 x86/x64 双平台构建,构建后的回归脚本 Deploy-Dependencies.ps1 可以直接当自建流水线的模板。
参数速查表
文件级转储
| 参数 | 需要 | 支持 JSON | 说明 |
|---|---|---|---|
-chain | 是 | 是 | 递归转储完整依赖链 |
-imports | 是 | 是 | 导入表(函数级) |
-exports | 是 | 是 | 导出表(名称/序数/VA/转发) |
-modules | 是 | 否 | 已解析模块扁平清单 |
-sxsentries | 是 | 是 | SxS 依赖项(未解析标???) |
-manifest | 是 | 是 | 内嵌 SxS 清单(XML) |
-assemblyrefs | 是 | 是 | .NET 程序集引用 |
-modulerefs | 是 | 是 | 模块引用 |
-apisetsdll | 是 | 是 | 从 apisetschema 文件转储 ApiSet 表 |
系统级查询
| 参数 | 需要 | 支持 JSON | 说明 |
|---|---|---|---|
-apisets | 否 | 是 | 转储系统 ApiSet 重定向表 |
-knowndll | 否 | 是 | 系统 KnownDlls 白名单(x86/x64) |
全局开关
| 参数 | 需要 | 支持 JSON | 说明 |
|---|---|---|---|
-json | 否 | — | 结果以缩进 JSON 格式输出 |
-cache | 否 | — | 启用二进制缓存,防止读取时文件锁定 |
-depth N | 否 | — | 限制依赖链递归深度,默认无限 |
-help | 否 | — | 显示完整帮助 |
小结
Dependencies 命令行版把 depends.exe 的排查能力压缩成一行脚本:-chain看全貌,-imports/-exports定函数,-json进 CI。建议的下一步:对主程序跑一次Dependencies.exe -chain -json,把输出归档为第一份依赖基线,之后的依赖漂移让流水线替你盯。
【免费下载链接】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),仅供参考