ILSpyCmd 反编译实战手册如何从 DLL 完整还原一个 .NET 项目【免费下载链接】ILSpy.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (more) - cross-platform!项目地址: https://gitcode.com/gh_mirrors/il/ILSpy先抛一个多数 .NET 开发者迟早会撞上的场景交接的旧系统没有源码仓库里只有几个编译好的 DLL可需求偏偏落在你头上——给这个模块加个功能。对着二进制文件无从下手时ILSpyCmd 就是那把打开保险箱的钥匙。它是 .NET 反编译器 ILSpy 的官方命令行版本跨平台、可脚本化能把程序集还原成可读的 C# 源码甚至重建出能直接编译的完整工程。这篇文章不打算罗列一堆命令参数而是跟着一次真实的源码考古流程从安装、还原、深入底层到接入自动化一步步把它的核心能力用起来。一次考古任务的开始你手里只有一个 DLL拿到程序集之后最自然的冲动是先看看里面有什么。与其直接双击打开图形界面慢慢点不如用命令行一次性把信息摊开。ILSpyCmd 的设计思路很简单一条命令对应一类任务输出既可以打到控制台也可以落到指定目录天然适合脚本和批处理。第一步装好工具让反编译跑起来通过 dotnet tool 一键安装只要本机装了 .NET SDK一条命令就能把 ilspycmd 装成全局工具dotnet tool install --global ilspycmd装完先确认版本顺便验证环境是否正常ilspycmd --version如果你更想自己从源码构建也可以把仓库克隆下来编译git clone https://gitcode.com/gh_mirrors/il/ILSpy拿到第一份反编译结果最简单的方式是把整个程序集的内容直接打到控制台ilspycmd app.dll输出会非常长所以更常用的做法是指定输出目录让结果落成一个文件ilspycmd -o src app.dll此时src目录下会生成一个以程序集命名的.cs文件里面是完整的 C# 源码。从这一步开始你就算读得懂这个二进制了。常见选项可以先记下这几个选项作用-o 目录指定输出目录几乎所有模式都能搭配使用-p反编译为可编译的项目必须配-o-t 类型名只反编译指定类型-m 文档ID或token只反编译指定成员-il输出 IL 中间代码-genpdb为程序集生成 PDB 调试文件-l 类型种类列出程序集里的类、接口、结构体等清单第二步缩小目标只反编译你想看的代码整包源码动辄上万行直接啃效率太低。考古的第一步是先勘探再定点挖掘。先列个清单心里有数想知道程序集里有哪些类、接口、结构体、委托和枚举用-l就能列出来后面可以跟一个或多个种类标识ilspycmd -l c,i,s app.dllc代表类class、i代表接口interface、s代表结构体struct还有ddelegate和eenum可用。输出是按行排列的完整类型名拿来当索引、或者配合 grep 过滤都很好用。按类型精确提取定位到目标后用-t指定完整类型名只反编译这一个类型ilspycmd -t OrderService -o src app.dll输出文件会以类型名命名方便直接对号入座。连一个方法都能单独拿出来更精细的需求是我只想看某个方法的实现。这时用-m参数可以是 XML 文档 ID 或者元数据 tokenilspycmd -m M:OrderService.CalculateTotal(System.Collections.Generic.List1) app.dll ilspycmd -m 0x06000005 app.dll文档 ID 的写法和编译器生成的 XML 注释文件一致token 则形如0x06000005。看单点实现、对比逻辑、排查特定方法时这个能力能省下大量翻找时间。第三步一键重建可编译工程反编译出零散源码只是第一步很多时候我们需要的是一个能直接dotnet build的完整工程。ILSpyCmd 的-p模式正是为此设计的。生成带工程文件的完整源码ilspycmd -p -o src app.dll这条命令会输出一个完整的项目结构每个类型一个独立的.cs文件外加.csproj工程文件依赖引用也会一并处理。拿到手就能打开编译相当于把二进制还原成了可维护的代码资产。让目录结构跟上命名空间程序集里命名空间一多所有文件平铺在一个目录里会很难受。加上--nested-directories源码会按命名空间分层存放ilspycmd --nested-directories -p -o src app.dll多个程序集一起还原直接得到解决方案-p模式还支持同时传入多个程序集每个程序集生成一个工程最后自动汇总出一个.sln解决方案文件ilspycmd -p -o src app.dll lib1.dll lib2.dll一个老系统往往由多个程序集组成这一条命令就能把整套工程骨架搭起来。控制反编译产出的风格默认输出使用当前最新的 C# 语法如果你要还原到老项目、需要兼容旧编译器可以用-lv指定语言版本ilspycmd -p -o src -lv CSharp7_3 app.dll此外-ds可以按名字值的形式覆盖任意反编译设置比如去掉死代码ilspycmd -p -o src -ds RemoveDeadCodeTrue app.dll如果桌面版 ILSpy 里已经调好了一套顺手的设置也可以用--ilspy-settingsfile直接把配置文件喂给命令行保证两种方式产出一致。第四步比源码更底层的视角还原出的 C# 代码偶尔会让人困惑这真的是原来的逻辑吗 这时候就需要下沉一层直接看 IL 中间代码或者借助调试信息交叉验证。查看 IL 中间代码-il模式输出程序集的完整 IL 指令想看带行号、能和源码对应的版本就加--il-sequence-pointsilspycmd -il app.dll ilspycmd --il-sequence-points app.dll当 C# 反编译结果出现歧义、或者怀疑有混淆/优化行为时IL 是最接近真相的参照物。为程序集生成 PDB 调试文件第三方库出问题想断点调试却没有 PDB让 ILSpyCmd 现场生成一个ilspycmd -genpdb app.dll生成的.pdb默认放在程序集旁边配合反编译出的源码调试第三方库就不再是黑盒碰运气了。用现有 PDB 还原变量名反过来如果程序集旁边本来就带着 PDB反编译时加上-usepdb就能用 PDB 里的变量名替换掉反编译器自动生成的名字可读性会大幅提升ilspycmd -usepdb app.dll转储元数据表对深入分析程序集结构的读者--dump-table可以把 ECMA-335 元数据表整表导出比如类型定义表ilspycmd --dump-table TypeDef app.dll ilspycmd --dump-table TypeDef --json app.dll--json目前只支持配合--dump-table使用输出 JSON 格式方便程序化消费。第五步把 WPF 程序的外壳也拆开遇到 WPF 程序集时光有 C# 源码还不够——界面长什么样、资源藏在哪都封装在资源文件甚至 BAML 里。ILSpyCmd 对这类资源同样提供了完整的处理链路。盘点程序集内嵌的资源先列清单ilspycmd --list-resources app.dll输出会逐条列出内嵌资源.resources容器里的条目还会以容器/条目的形式单独展开BAML 资源也在其中。提取单个资源按清单里的名字提取指定资源名称以.baml结尾的会自动反编译成 XAML其余按原始字节导出ilspycmd --resource app.g.resources/mainwindow.baml -o out app.dll反编译整个工程时顺带还原 BAML配合-p使用--decompile-baml项目里所有 BAML 资源会转成 XAML 并作为 Page 项纳入工程ilspycmd -p -o src --decompile-baml app.dll这样一来WPF 程序的界面文件也一起复活了还原度几乎和拿到原始工程无异。第六步让架构一目了然的交互式图表源码看多了容易只见树木不见森林尤其面对一个陌生的大型程序集时先整体摸清类型之间的关系比逐行读代码高效得多。--generate-diagrammer可以直接生成一个交互式 HTML 架构图ilspycmd app.dll --generate-diagrammer默认会在程序集旁边生成一个diagrammer文件夹打开 HTML 就能看到基于 Mermaid 渲染的类型关系图点击、展开、过滤都可以在浏览器里完成写技术文档、做代码评审前的架构摸底都很合适。用正则圈定范围避免图大失控大型程序集直接全量出图会非常慢文件体积也很吓人。可以用正则限定包含/排除范围ilspycmd app.dll --generate-diagrammer \ --generate-diagrammer-include Order\\.. \ --generate-diagrammer-exclude .\\Metadatainclude是白名单exclude是黑名单两者都按类型的FullName匹配。拿不准正则写没写对时加一个--generate-diagrammer-report-excluded会输出一份被排除类型的报告方便调试过滤规则。把 XML 文档注释也画进图里想让架构图带上类型说明可以指定 XML 文档文件注释里不想显示的命名空间前缀也能顺手剥掉ilspycmd app.dll --generate-diagrammer \ --generate-diagrammer-docs app.xml \ --generate-diagrammer-strip-namespaces System.Collections Generic System第七步把反编译接进自动化流水线命令行工具的终极价值在于无人值守。架构图这种东西最好的维护方式就是每次构建/发布后自动重新生成保证文档永远和代码同步。发布后自动出图在.csproj里加一个 MSBuild Target挂在Publish之后Target NameGenerateHtmlDiagrammer AfterTargetsPublish Exec Commandilspycmd $(TargetPath) --generate-diagrammer --outputdir $(PublishDir)diagrammer / /Target想放在Build之后、或者限定只在 Release 配置下执行把AfterTargets和Condition改一下即可思路完全一样。CI 流水线里也可以直接用命令行调用效果相同。脚本里必须懂的退出码自动化脚本最怕失败了还假装成功。ilspycmd 的退出码遵循 sysexits 约定参数错误返回 64输入数据有问题返回 65文件不存在返回 66反编译过程出现内部错误返回 70。尤其要注意只要部分代码没能反编译成功默认就会返回非零退出码错误详情会打到 stderr。如果只是尽量还原个别失败可以接受可以显式声明ilspycmd -p -o src --ignore-decompilation-errors app.dll这样即使有部分代码还原失败退出码也是 0但失败的详情仍会写到 stderr方便事后排查。循环调用时关闭更新检查每次运行时 ilspycmd 默认会联网检查一次工具更新在批处理或 CI 里高频调用时会造成无谓延迟用--disable-updatecheck关掉ilspycmd --disable-updatecheck -p -o src app.dll实战中容易踩的坑最后把高频问题集中说一下遇到时能少走不少弯路-p必须搭配-o项目模式要求显式指定输出目录只写-p会直接报用法错误。-t和-m互斥类型和成员不能同时指定一次只干一件事。依赖缺失导致还原不完整程序集引用的第三方 DLL 找不到时用-r追加依赖搜索目录ilspycmd -p -o src -r ./deps app.dll大程序集出图前先缩小范围先反编译源码摸清子域再用--generate-diagrammer-include/exclude圈定范围否则构建时间、文件体积和浏览器打开速度都会很难受。反编译失败不等于没有输出失败时受影响代码位置会写入错误文本源码仍会生成务必检查 stderr 和退出码别被文件都在骗过去。--json不能单独使用它目前只服务于--dump-table单独传会报错。收尾从读代码到维护系统回到开头的场景那个只剩 DLL 的老系统现在你可以列类型、看方法、还原整个工程、生成 PDB 断点调试、把 BAML 界面挖出来、再顺手生成一张架构图归档。一套流程下来二进制对你来说已经不再是黑盒而是可以阅读、编译、维护的普通代码。工具本身并不复杂真正值钱的是一套从二进制到可维护资产的工作流。建议你现在就装好 ilspycmd随便找一份手头的 DLL 试试先-l列清单再-t抽一个类型最后-p看看能不能把整个工程重建出来。亲手跑通一遍比看十篇教程都管用。【免费下载链接】ILSpy.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (more) - cross-platform!项目地址: https://gitcode.com/gh_mirrors/il/ILSpy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考