☰
一次讲透 Dependencies 命令行:从依赖树到 JSON 接入 CI 流水线实战
2026/11/4 1:21:24 网站建设 项目流程

一次讲透 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,所以命令行版的分析结果可以直接作为排查依据。

获取方式只有两种:

  1. 下载发布包:从 Releases 页取 zip 解压即用,无需安装器。
  2. 源码构建:
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

三种玩法:

  1. 依赖基线 diff:每次构建后导出依赖快照,与基线做 diff,依赖集悄悄变化就能被逮住;
  2. 缺失 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 "存在缺失依赖,流水线失败" }
  1. 报告归档:把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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询