调试
您可以使用 Microsoft C# 扩展在 Visual Studio Code 中调试 C# 应用程序。
运行和调试
C# 扩展以及 C# Dev Kit 提供多种方法来运行和调试 C# 应用程序。
要运行和调试而无需 C# Dev Kit,请参阅 Microsoft C# 扩展的 GitHub 页面 获取文档。
使用 F5 调试
安装 C# Dev Kit 扩展后,如果没有可供选择的调试配置,则可以通过打开一个 .cs
文件,然后按 F5 来开始调试项目。调试器会自动找到项目并开始调试。如果您有多个项目,它会提示您选择要调试的项目。
您也可以从 VS Code 侧栏的 **运行和调试** 视图开始调试会话。有关详细信息,请参阅 在 VS Code 中调试。
使用解决方案资源管理器调试
安装 C# Dev Kit 扩展后,在解决方案资源管理器中右键单击项目时会出现一个 **调试** 上下文菜单。
有三个选项
- **启动新实例** - 这将在附加调试器的情况下启动项目。
- **不调试启动** - 这将在不附加调试器的情况下运行项目。
- **单步执行到新实例** - 这将在附加调试器的情况下启动项目,但在代码的入口点处停止。
使用命令面板调试
安装 C# Dev Kit 扩展后,您也可以通过使用 **调试:选择并开始调试** 命令,从命令面板 ⇧⌘P(Windows、Linux Ctrl+Shift+P) 开始调试。
注意:这会将启动配置条目添加到您的调试下拉列表中。
使用动态(内存中)启动配置调试
安装 C# Dev Kit 扩展后,您可以创建动态启动配置。如何创建取决于您的项目是否具有现有的 launch.json
文件。
现有 launch.json
如果您具有现有的 launch.json
,则可以转到调试视图,选择下拉菜单,然后选择 C#
选项。这应该会为您提供要添加到下拉列表中的启动目标选择。选择后,您可以按 F5 或使用新生成的配置 **开始调试**。
没有 launch.json
如果您在项目中没有 launch.json
,则可以在调试视图的 **显示所有自动调试配置** 中添加和访问这些动态配置。
删除动态(内存中)启动配置
您可以使用命令面板 ⇧⌘P(Windows、Linux Ctrl+Shift+P) 并使用命令 **调试:选择并开始调试** 来删除生成的配置。
在下拉菜单中,它列出了所有现有的调试配置。如果您将鼠标悬停在动态配置上,则在右侧会出现一个可点击的垃圾桶图标。您可以选择该图标来删除动态配置。
使用 launch.json 调试
如果您正在使用 C# Dev Kit,我们建议您不要使用此选项。但是,如果您需要直接修改调试配置,请参阅 为 C# 调试配置 launch.json。
连接到进程
您可以使用命令面板 ⇧⌘P(Windows、Linux Ctrl+Shift+P) 并运行 **调试:附加到 .NET 5+ 或 .NET Core 进程** 命令,连接到 C# 进程。
配置选项
有多种选项和设置可用于配置调试器。您可以使用 launchSettings.json
、VS Code 的 用户设置 来修改您的调试选项,或者直接修改 launch.json
。
launchSettings.json
如果您从 Visual Studio 那里获得了 launchSettings.json
,则应该使用 从 F5 运行 或 从命令面板运行 查看您的配置文件列表。
有关详细信息,请参阅 配置 C# 调试。
用户设置
如果您希望在使用 C# 调试器时更改设置,则可以在 文件 > 首选项 > 设置 (⌘,(Windows、Linux Ctrl+,)) 中找到这些选项,并搜索这些选项。
csharp.debug.stopAtEntry
- 如果为 true,则调试器应该在目标的入口点处停止。此选项默认为false
。csharp.debug.console
- 在启动控制台项目时,指示目标程序应在哪个控制台中启动。注意:此选项仅适用于“dotnet”调试配置类型。internalConsole
[默认] - VS Code 的调试控制台。此模式允许您在同一个地方查看调试器和目标程序发出的消息。有关详细信息,请参阅 完整文档。integratedTerminal
- VS Code 的集成终端。externalTerminal
- 可以通过用户设置配置的外部终端。
csharp.debug.sourceFileMap
- 将构建时路径映射到本地源位置。所有构建时路径实例都将被替换为本地源路径。
示例
{\"<build-path>\":\"<local-source-path>\"}
csharp.debug.justMyCode
- 启用时(默认),调试器仅显示和单步执行用户代码(“我的代码”),忽略系统代码以及经过优化或没有调试符号的其他代码。更多信息。csharp.debug.requireExactSource
- 要求当前源代码与 pdb 匹配的标志。此选项默认为true
。csharp.debug.enableStepFiltering
- 启用跳过属性和运算符的标志。此选项默认为true
。csharp.debug.logging.exceptions
- 用于确定是否将异常消息记录到输出窗口的标志。此选项默认为true
。csharp.debug.logging.moduleLoad
- 用于确定是否将模块加载事件记录到输出窗口的标志。此选项默认为true
。csharp.debug.logging.programOutput
- 用于确定在不使用外部控制台的情况下是否将程序输出记录到输出窗口的标志。此选项默认为true
。csharp.debug.logging.diagnosticsLog
- 用于诊断调试器问题时的各种设置。csharp.debug.logging.browserStdOut
- 用于确定是否将启动 Web 浏览器产生的标准输出文本记录到输出窗口的标志。此选项默认为true
。csharp.debug.logging.elapsedTiming
- 如果为 true,引擎日志将包含adapterElapsedTime
和engineElapsedTime
属性,以指示请求花费的时间(以微秒为单位)。此选项默认为false
。csharp.debug.logging.threadExit
- 控制是否在目标进程中的线程退出时记录消息。此选项默认为false
。csharp.debug.logging.processExit
- 控制是否在目标进程退出或调试停止时记录消息。此选项默认为true
。csharp.debug.suppressJITOptimizations
- 如果为 true,当目标进程加载优化模块(以 Release 配置编译的 .dll)时,调试器会要求即时编译器生成禁用优化的代码。更多信息csharp.debug.symbolOptions.searchPaths
- 用于搜索 .pdb 文件的符号服务器 URL(例如:http://MyExampleSymbolServer
)或目录(例如:/build/symbols)的数组。除了模块旁边的默认位置和 pdb 最初放置的路径之外,还将在这些目录中搜索。csharp.debug.symbolOptions.searchMicrosoftSymbolServer
- 如果为true
,则将 Microsoft 符号服务器(https://msdl.microsoft.com/download/symbols
)添加到符号搜索路径中。如果未指定,则此选项默认为false
。csharp.debug.symbolOptions.searchNuGetOrgSymbolServer
- 如果为true
,则将 NuGet.org 符号服务器(https://symbols.nuget.org/download/symbols
)添加到符号搜索路径中。如果未指定,则此选项默认为false
。csharp.debug.symbolOptions.cachePath
- 从符号服务器下载的符号应缓存在其中的目录。如果未指定,则在 Windows 上,调试器默认为%TEMP%\\SymbolCache
,而在 Linux 和 macOS 上,调试器默认为~/.dotnet/symbolcache
。csharp.debug.symbolOptions.moduleFilter.mode
- 控制模块过滤器运行的两种基本操作模式中的哪一种。loadAllButExcluded
- 加载所有模块的符号,除非模块位于excludedModules
数组中。loadOnlyIncluded
- 除非模块位于includedModules
数组中,或者通过includeSymbolsNextToModules
设置包含,否则不要尝试加载任何模块的符号。
csharp.debug.symbolOptions.moduleFilter.excludedModules
- 调试器不应加载其符号的模块数组。支持通配符(例如:MyCompany.*.dll)。除非mode
设置为loadAllButExcluded
,否则将忽略此属性。csharp.debug.symbolOptions.moduleFilter.includedModules
- 调试器应加载其符号的模块数组。支持通配符(例如:MyCompany.*.dll)。除非mode
设置为loadOnlyIncluded
,否则将忽略此属性。csharp.debug.symbolOptions.moduleFilter.includeSymbolsNextToModules
- 如果为 true,则对于不在includedModules
数组中的任何模块,调试器仍将检查模块本身和启动的可执行文件旁边,但它不会检查符号搜索列表中的路径。此选项默认为true
。除非mode
设置为loadOnlyIncluded
,否则将忽略此属性。csharp.debug.allowFastEvaluate
- 当为 true(默认状态)时,调试器将尝试通过模拟简单属性和方法的执行来进行更快的评估。csharp.experimental.debug.hotReload
- 当为 true 时,如果目标应用程序支持热重载,调试器将启用在调试时应用更改。csharp.debug.hotReloadOnSave
- 当为 true(默认状态)时,调试器将在保存文件时自动应用代码更改。csharp.debug.hotReloadVerbosity
- 控制 **C# 热重载** 输出窗口的日志详细程度。可以将其设置为minimal
(默认)、detailed
或diagnostic
。如果热重载开始出现意外行为,建议提高详细程度级别。
断点
C# 调试器支持各种断点,例如源代码行断点、条件断点和日志点。
断点 - 条件断点
借助表达式评估,调试器还支持条件断点。您可以将断点设置为在表达式评估为 true 时中断。
断点 - 函数断点
调试器还支持函数断点。您可以通过单击调试窗格的“断点”部分中的“+”来设置您的断点,使其在特定函数上中断。
断点 - 日志点
日志点(在 Visual Studio 中也称为跟踪点)允许您将输出发送到调试控制台,而无需编辑代码。它们不同于断点,因为它们不会停止应用程序的执行流程。
要添加日志点,请右键单击代码行旁边的最左侧边距。选择“添加日志点”并键入您要记录的消息。任何在大括号(“{”和“}”)之间的表达式将在命中日志点时进行评估。
日志消息中还支持以下标记
标记 | 描述 | 示例输出 |
---|---|---|
$FILEPOS | 当前源代码文件位置 | C:\sources\repos\Project\Program.cs:4 |
$FUNCTION | 当前函数名称 | Program.<Main>$ |
$ADDRESS | 当前指令 | 0x00007FFF83A54001 |
$TID | 线程 ID | 20668 |
$PID | 进程 ID | 10028 |
$TNAME | 线程名称 | <No Thread Name> |
$PNAME | 进程名称 | C:\sources\repos\Project\bin\Debug\net7.0\console.exe |
$CALLER | 调用函数名称 | void console.dll!Program.Foo() |
$CALLSTACK | 调用堆栈 | void console.dll!Program.Bar() void console.dll!Program.Foo() void console.dll!Program.<Main>$(string[] args) [External Code] |
$TICK | 滴答计数(来自 Windows GetTickCount) | 28194046 |
$HITCOUNT | 此断点命中的次数 | 5 |
断点 - 触发断点
触发断点是在命中另一个断点后自动启用的断点。在诊断仅在特定前提条件满足后才会发生的代码中的故障情况时,它们非常有用。
可以通过右键单击图示边距,选择“添加触发断点”,然后选择哪个其他断点启用该断点来设置触发断点。
在异常处停止
C# 调试器支持在抛出或捕获异常时调试器停止的配置选项。这通过 **运行** 视图的 **断点** 部分中的两个不同条目完成。
请注意,在第一次使用 C# 调试器调试该文件夹之前,**断点** 部分将缺少这些条目。
选中 **所有异常** 将配置调试器在抛出异常时停止。如果启用了 仅我的代码(默认情况下已启用),则如果在库代码中内部抛出并捕获异常,调试器将不会中断。但是,如果异常是在库代码中抛出并返回到用户代码,调试器将中断。
选中 **用户未处理的异常** 将配置调试器在非用户代码中捕获异常时停止,该异常是在用户代码中抛出或经过用户代码后发生的。导致用户未处理的异常并不总是被调试进程中的错误 - 可能是用户代码正在实现 API,并且预期会引发异常。在很多情况下,确实存在问题,因此,默认情况下,调试器将在异常变为用户未处理时停止。
异常条件
两个复选框都支持条件,以仅对选定的异常类型进行中断。要编辑条件,请选择铅笔图标(见上图),或右键单击该条目并调用“编辑条件”。条件是一个逗号分隔的异常类型列表,用于中断,或者如果列表以“!”开头,则为要忽略的异常类型列表。
示例条件
示例条件值 | 结果 |
---|---|
System.NullReferenceException | 这将仅在空引用异常时中断。 |
System.NullReferenceException, System.InvalidOperationException | 这将同时在空引用异常和无效操作异常时中断。 |
!System.Threading.Tasks.TaskCanceledException | 这将对除任务取消之外的所有异常中断。 |
!System.Threading.Tasks.TaskCanceledException, System.NotImplementedException | 这将对除任务取消和未实现之外的所有异常中断。 |
表达式计算
调试器还允许您在 **监视** 窗口和调试控制台中评估表达式。
热重载
安装了 C# Dev Kit 扩展后,调试器允许您在调试时应用 C# 代码更改。
为了启用热重载,csharp.experimental.debug.hotReload
必须设置为 true,有关更多信息,请参阅 用户设置。只有当目标调试器引擎支持应用代码更改时,热重载会话才会启动。
支持的项目和场景
C# Dev Kit 支持“经典”热重载体验,也称为编辑并继续。无论您是在断点处停止还是程序正在运行,您都可以在调试时应用代码更改。
截至 2023 年 11 月,一些功能(例如 MetadataUpdateHandler
)尚不可用,MetadataUpdateHandler
允许 ASP.NET Core 应用程序在 进行更改后自动刷新浏览器。在不进行调试的情况下应用代码更改也不受支持。
运行时在 .NET 8 中为在 Linux/macOS 上调试时应用更改添加了支持,因此在针对这些操作系统上运行的 .NET 应用程序应用代码更改时,需要 .NET 8+ 的运行时版本。
应用程序类型 | 支持使用 C# Dev Kit 进行热重载 | .NET 8+ 要求 |
---|---|---|
控制台 | ✅ | 仅 Linux/macOS |
测试项目 | ✅ | 仅 Linux/macOS |
类库项目 | ✅ | 仅 Linux/macOS |
ASP.NET Core | ⚠️* 目前仅支持对 .cs 文件的更改 |
仅 Linux/macOS |
MAUI | ❌* 即将推出 | -- |
Unity | ❌ | -- |
有关 C# Dev Kit 当前支持的项目的更多信息,请参阅 支持的项目。有关解决其他不受支持的场景的更多信息,请参阅 C# Dev Kit 常见问题解答。
如何应用代码更改
热重载会话启动后,如果进行了新的更改,您可以使用以下任何操作将这些更改应用于应用程序
操作 | 解释 |
---|---|
热重载 Ctrl+Shift+Enter |
应用代码更改,可从 **调试工具栏** 中使用。 |
保存文件 ⌘S(Windows、Linux Ctrl+S) |
如果 csharp.debug.hotReloadOnSave 设置为 true,则开始应用代码更改。有关更多信息,请参阅 用户设置。 |
继续 / 逐句执行 / 逐过程执行 / 逐过程退出 F5 / F10 / F11 / ⇧F11(Windows、Linux Shift+F11) |
当在暂停状态(例如,在断点处停止)进行更改时,这些命令将自动应用它们。 |
后续步骤
继续阅读以了解更多关于
- 调试 - 了解如何在 VS Code 中使用调试器与您的任何语言项目。