问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

调试时从 .NET 程序集生成源代码

创作时间:
作者:
@小白创作中心

调试时从 .NET 程序集生成源代码

引用
1
来源
1.
https://learn.microsoft.com/zh-cn/visualstudio/debugger/decompilation?source=recommendations&view=vs-2022

在.NET应用程序的调试过程中,经常会遇到需要查看源代码的情况,但有时源代码并不总是可用。本文将详细介绍如何在Visual Studio 2022中从.NET程序集生成源代码,包括手动反编译、自动反编译以及使用SourceLink等功能,并探讨了反编译的限制和注意事项。

调试 .NET 应用程序时,你可能会发现需要查看尚未拥有的源代码。 例如,中断异常或使用调用堆栈导航到源位置。

生成源代码

进行调试但没有可用的源代码时,Visual Studio 会显示“找不到源代码”文档,或者,如果没有用于程序集的符号,则显示“未加载任何符号”文档。 这两个文档都有一个反编译源代码选项,该选项为当前位置生成 C# 代码。 然后,生成的 C# 代码可以像任何其他源代码一样使用。 可以查看代码、检查变量、设置断点等。

未加载任何符号

下图显示了“未加载任何符号”消息。

找不到源

下图显示了“找不到源代码”消息。

自动反编译代码

从 Visual Studio 2022 版本 17.7 开始,Visual Studio 调试器支持自动编译外部 .NET 代码。 在步入外部代码或使用“调用堆栈”窗口时,您可以自动反编译。

如果进入已在外部实现的代码,调试器会自动反编译它,并显示当前的执行位置。 如果要单步执行外部代码,请禁用仅我的代码。

可以从“调用堆栈”窗口反编译,而无需禁用“仅我的代码”。

要从“调用堆栈”窗口自动反编译,请执行以下操作:

  1. 打开“调用堆栈”窗口进行调试时,选择“显示外部代码”。
  2. 在“调用堆栈”窗口中,双击任何堆栈帧。 调试器将反编译代码,然后直接导航到当前执行点。

解决方案资源管理器中的“外部源”节点下也显示了所有反编译代码,以便在需要时轻松浏览外部文件。

可以调试反编译代码并设置断点。

若要禁用外部代码的自动反编译,请转到“工具”>“选项”>“调试”>“常规”,并取消选择“在需要时自动反编译到源(仅限托管)”。

为程序集生成和嵌入源代码

除了为特定位置生成源代码外,还可以为给定的 .NET 程序集生成所有源代码。 若要执行此任务,请转到模块窗口,然后从 .NET 程序集的上下文菜单中选择“将源反编译到符号文件命令。 Visual Studio 为程序集生成符号文件,然后将源嵌入符号文件中。 在后续步骤中,可以提取嵌入的源代码。

提取并查看嵌入的源代码

可以使用“提取源代码”命令在“模块”窗口的上下文菜单中提取嵌入在符号文件中的源文件。

提取的源文件已被添加到解决方案中,作为杂项文件。 默认情况下,Visual Studio 中的杂项文件功能处于关闭状态。 可以从工具>选项>环境>文档>解决方案资源管理器中的“显示杂项文件”复选框启用此功能。 如果未启用此功能,则无法打开提取的源代码。

提取的源文件显示在解决方案资源管理器杂项文件中。

SourceLink

对于支持 SourceLink 的 .NET 库或 NuGet 包,您还可以进入源代码、设置断点并使用所有调试功能。 有关详细信息,请参阅使用源链接启用调试和诊断,使用 SourceLink提高调试时工作效率。

已知限制

需要中断模式

仅当调试器处于中断模式且应用程序暂停时,才能使用反编译生成源代码。 例如,Visual Studio 遇到断点或异常时会进入中断模式。 可以使用命令Break All(图标
)轻松触发 Visual Studio 在代码下次运行时暂停。

反向编译的限制

从 .NET 程序集中使用的中间格式(IL)生成源代码具有一些固有的限制。 因此,生成的源代码与原始源代码不同。 大多数差异位于运行时不需要原始源代码中信息的位置。 例如,运行时不需要空格、注释和局部变量的名称等信息。 建议使用生成的源来了解程序的执行方式,而不是原始源代码的替代方法。

调试优化或发布的程序集

当调试从使用编译器优化编译的程序集中反编译的代码时,可能会遇到以下问题:

  • 断点可能并不总是绑定到匹配的源位置。
  • 单步执行可能并不总是进行到正确的位置。
  • 局部变量可能没有准确的名称。
  • 某些变量可能不可用于评估。

GitHub 问题中可以找到更多详细信息:ICSharpCode.Decompiler 集成到 VS Debugger。

反向编译的可靠性

进行反编译尝试时,仅有一小部分可能会失败。 此行为是由于 ILSpy 中的序列点 null 引用错误导致的。 我们通过捕获这些问题并重现失败过程来减少反向编译失败。

GitHub 问题中可以找到更多详细信息:ICSharpCode.Decompiler 集成到 VS Debugger。

异步代码的限制

使用异步/await 代码模式反编译模块的结果可能不完整或完全失败。 异步/等待和暂停状态机的 ILSpy 实现仅部分实现。

可在 GitHub 问题中找到更多详细信息:PDB 生成器状态。

仅我的代码

“仅我的代码”(JMC)设置允许 Visual Studio 跳过系统代码、框架代码、库代码以及其他非用户代码调用。 在调试会话期间,“模块”窗口显示调试器将视为“我的代码”(用户代码)的代码模块。

对优化或发布模块进行反编译会生成非用户代码。 例如,如果调试器中断了反向编译的非用户代码,则会显示“无源代码”窗口。 若要禁用“仅我的代码”,请导航到“工具>选项(或调试>选项)>调试>常规,然后取消选择”启用仅我的代码“

提取的资源

从程序集中提取的源代码具有以下限制:

  • 生成的文件的名称和位置不可配置。
  • 这些文件是临时的,由 Visual Studio 删除。
  • 这些文件放置在单个文件夹中,不使用原始源的任何文件夹层次结构。
  • 每个文件的文件名都包含该文件的校验和哈希。

生成的代码仅为 C#

反编译仅生成 C# 中的源代码文件。 无法选择以任何其他语言生成文件。

本文原文来自微软官方文档

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号