调试
Visual Studio Code 的关键特性之一是其出色的调试支持。VS Code 的内置调试器有助于加速您的编辑、编译和调试循环。
用户界面
下图显示了调试用户界面的主要组件:
- 运行和调试视图: 显示与运行、调试和管理调试配置设置相关的所有信息。
- 调试工具栏:包含最常用调试操作的按钮。
- 调试控制台:允许查看并与调试器中运行的代码输出进行交互。
- 调试侧边栏:在调试会话期间,允许您与调用堆栈、断点、变量和监视变量进行交互。
调试器扩展
VS Code 内置了对 Node.js 运行时的调试支持,并且可以调试 JavaScript、TypeScript 或任何其他被转译为 JavaScript 的语言。
为了调试其他语言和运行时(包括 PHP, Ruby, Go, C#, Python, C++, PowerShell 和 许多其他),请在 VS Code 的 Marketplace 中查找 Debuggers
扩展,或在顶层的运行菜单中选择 安装其他调试器。
以下是几个包含调试支持的流行扩展:
提示:上面显示的扩展是动态查询的。选择一个上面的扩展磁贴,阅读描述和评论,以决定哪个扩展最适合您。
开始调试
以下文档基于内置的Node.js调试器,但大多数概念和功能也适用于其他调试器。
在阅读有关调试的内容之前,首先创建一个示例Node.js应用程序是有帮助的。您可以按照Node.js教程来安装Node.js并创建一个简单的“Hello World”JavaScript应用程序(app.js
)。一旦您设置了一个简单的应用程序,本页面将带您了解VS Code的调试功能。
运行和调试视图
要打开运行和调试视图,请在VS Code侧边的活动栏中选择运行和调试图标。你也可以使用键盘快捷键⇧⌘D (Windows, Linux Ctrl+Shift+D)。
运行和调试视图显示与运行和调试相关的所有信息,并具有一个包含调试命令和配置设置的顶部栏。
如果尚未配置运行和调试(未创建launch.json
),VS Code 会显示运行启动视图。
运行菜单
顶层的运行菜单包含最常见的运行和调试命令:
启动配置
要在VS Code中运行或调试一个简单的应用程序,请在调试启动视图中选择运行和调试或按下F5,VS Code将尝试运行您当前活动的文件。
然而,对于大多数调试场景,创建启动配置文件是有益的,因为它允许您配置和保存调试设置细节。VS Code 将调试配置信息保存在工作区(项目根文件夹)中的 .vscode
文件夹内的 launch.json
文件中,或者保存在您的 用户设置 或 工作区设置 中。
要创建launch.json
文件,请在运行开始视图中选择创建launch.json文件。
VS Code 将尝试自动检测您的调试环境,但如果失败,您将需要手动选择它:
这是为Node.js调试生成的启动配置:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}\\app.js"
}
]
}
如果你返回到文件资源管理器视图(⇧⌘E (Windows, Linux Ctrl+Shift+E)),你会看到VS Code已经创建了一个.vscode
文件夹,并将launch.json
文件添加到了你的工作区。
注意: 即使你没有在VS Code中打开文件夹,也可以调试一个简单的应用程序,但无法管理启动配置和设置高级调试。如果你没有打开文件夹,VS Code状态栏会显示为紫色。
请注意,启动配置中可用的属性因调试器而异。您可以使用IntelliSense建议(⌃Space (Windows, Linux Ctrl+Space))来查找特定调试器存在哪些属性。所有属性也都有悬停帮助。
不要假设一个调试器可用的属性自动适用于其他调试器。如果您在启动配置中看到红色波浪线,请将鼠标悬停在它们上面以了解问题所在,并在启动调试会话之前尝试修复它们。
审查所有自动生成的值,并确保它们对您的项目和调试环境有意义。
启动与附加配置
在VS Code中,有两种核心调试模式,启动和附加,它们处理两种不同的工作流程和开发者群体。根据你的工作流程,可能会混淆哪种类型的配置适合你的项目。
如果你有浏览器开发者工具的背景,你可能不习惯“从你的工具启动”,因为你的浏览器实例已经打开。当你打开开发者工具时,你只是将开发者工具附加到你打开的浏览器标签上。另一方面,如果你有服务器或桌面背景,让你的编辑器为你启动进程是很正常的,你的编辑器会自动将其调试器附加到新启动的进程上。
解释launch和attach之间区别的最佳方式是将launch配置视为在VS Code附加到应用程序之前如何以调试模式启动应用程序的配方,而attach配置则是如何将VS Code的调试器连接到已经运行的应用程序或进程的配方。
VS Code 调试器通常支持在调试模式下启动程序或附加到已经在调试模式下运行的程序。根据请求(attach
或 launch),需要不同的属性,VS Code 的 launch.json
验证和建议应该对此有所帮助。
添加新配置
要向现有的launch.json
添加新配置,请使用以下技术之一:
- 如果光标位于配置数组内,请使用 IntelliSense。
- 按下添加配置按钮以在数组开头调用代码片段智能感知。
- 在运行菜单中选择添加配置选项。
VS Code 还支持复合启动配置,以便同时启动多个配置;有关更多详细信息,请阅读此部分。
为了启动调试会话,首先在运行和调试视图中使用配置下拉菜单选择名为启动程序的配置。一旦设置好启动配置,就可以使用F5开始调试会话。
或者,您可以通过命令面板(⇧⌘P(Windows, Linux Ctrl+Shift+P))运行您的配置,通过过滤调试:选择并开始调试或输入'debug '
并选择您想要调试的配置。
一旦调试会话开始,DEBUG CONSOLE面板就会显示并展示调试输出,状态栏的颜色也会改变(对于默认颜色主题为橙色):
此外,调试状态会出现在状态栏中,显示当前活动的调试配置。通过选择调试状态,用户可以更改当前活动的启动配置并开始调试,而无需打开运行和调试视图。
调试操作
一旦调试会话开始,调试工具栏将出现在窗口的顶部。
Action | Explanation |
---|---|
Continue / Pause F5 |
Continue: Resume normal program/script execution (up to the next breakpoint). Pause: Inspect code executing at the current line and debug line-by-line. |
Step Over F10 |
Execute the next method as a single command without inspecting or following its component steps. |
Step Into F11 |
Enter the next method to follow its execution line-by-line. |
Step Out ⇧F11 (Windows, Linux Shift+F11) |
When inside a method or subroutine, return to the earlier execution context by completing remaining lines of the current method as though it were a single command. |
Restart ⇧⌘F5 (Windows, Linux Ctrl+Shift+F5) |
Terminate the current program execution and start debugging again using the current run configuration. |
Stop ⇧F5 (Windows, Linux Shift+F5) |
Terminate the current program execution. |
提示: 使用设置 debug.toolBarLocation 来控制调试工具栏的位置。它可以是默认的
floating
,docked
到 运行和调试 视图,或者hidden
。一个floating
调试工具栏可以水平拖动,也可以向下拖动到编辑器区域(距离顶部边缘一定距离内)。
运行模式
除了调试程序外,VS Code 还支持运行程序。调试:启动而不调试操作通过⌃F5(Windows, Linux Ctrl+F5)触发,并使用当前选择的启动配置。许多启动配置属性在“运行”模式下都受支持。VS Code 在程序运行时维护一个调试会话,按下停止按钮将终止程序。
提示: 运行操作始终可用,但并非所有调试器扩展都支持“运行”。在这种情况下,“运行”将与“调试”相同。
断点
可以通过点击编辑器边距或使用当前行的F9来切换断点。更精细的断点控制(启用/禁用/重新应用)可以在运行和调试视图的断点部分完成。
- 编辑器边距中的断点通常显示为红色实心圆。
- 禁用的断点有一个填充的灰色圆圈。
- 当调试会话开始时,无法在调试器中注册的断点会变为灰色的空心圆圈。如果在没有实时编辑支持的调试会话运行时编辑源代码,也可能会发生同样的情况。
如果调试器支持在不同类型的错误或异常上中断,这些选项也将在断点视图中可用。
重新应用所有断点命令将所有断点再次设置到其原始位置。如果您的调试环境“懒惰”并且“错放”了尚未执行的源代码中的断点,这将非常有用。
可选地,可以通过启用设置 debug.showBreakpointsInOverviewRuler 来在编辑器的概览标尺中显示断点:
日志点
日志点是断点的一种变体,它不会“中断”进入调试器,而是将消息记录到调试控制台。日志点使您能够在调试时注入日志记录,而无需修改源代码。当您调试无法暂停或停止的生产服务器时,它们尤其有用。日志点还可以帮助您节省时间,因为您不必在代码中添加或删除日志记录语句。
日志点由一个“菱形”图标表示。日志消息是纯文本,但可以包含在大括号('{}')内评估的表达式。
在左侧编辑器装订线上下文菜单中使用添加日志点命令,或使用调试:添加日志点...命令添加日志点。您还可以配置设置debug.gutterMiddleClickAction,以便在编辑器装订线中按下鼠标中键时切换日志点。
就像常规断点一样,日志点可以被启用或禁用,并且也可以通过条件和/或命中次数来控制。
注意: Logpoints 由 VS Code 内置的 Node.js 调试器支持,但也可以由其他调试扩展实现。例如,Python 和 Java 扩展支持 Logpoints。
数据检查
变量可以在运行和调试视图的变量部分进行检查,或者通过将鼠标悬停在编辑器中的源代码上来查看。变量值和表达式评估是相对于调用堆栈部分中选定的堆栈帧的。
变量的值可以通过变量上下文菜单中的Set Value操作进行修改。此外,您可以使用Copy Value操作来复制变量的值,或者使用Copy as Expression操作来复制访问变量的表达式。
变量和表达式也可以在运行和调试视图的WATCH部分中进行评估和监视。
当焦点位于变量部分时,可以通过输入来过滤变量名称和值。
Launch.json 属性
有许多launch.json
属性可以帮助支持不同的调试器和调试场景。如上所述,一旦您为type
属性指定了值,您可以使用IntelliSense(⌃Space (Windows, Linux Ctrl+Space))来查看可用属性的列表。
每个启动配置都必须具备以下属性:
type
- 用于此启动配置的调试器类型。每个已安装的调试扩展都会引入一个类型:例如,内置的Node调试器为node
,PHP和Go扩展分别为php
和go
。request
- 此启动配置的请求类型。目前支持 launch 和attach
。name
- 在调试启动配置下拉菜单中显示的读者友好名称。
以下是一些适用于所有启动配置的可选属性:
presentation
- 使用presentation
对象中的order
、group
和hidden
属性,您可以在调试配置下拉菜单和调试快速选择中对配置和组合进行排序、分组和隐藏。preLaunchTask
- 在调试会话开始之前启动任务,将此属性设置为tasks.json(在工作区的.vscode
文件夹中)指定的任务的标签。或者,可以将其设置为${defaultBuildTask}
以使用默认的构建任务。postDebugTask
- 要在调试会话的最后启动一个任务,请将此属性设置为在tasks.json(在工作区的.vscode
文件夹中)中指定的任务的名称。internalConsoleOptions
- 此属性控制调试会话期间调试控制台面板的可见性。debugServer
- 仅适用于调试扩展作者:此属性允许您连接到指定的端口,而不是启动调试适配器。serverReadyAction
- 如果您希望在调试的程序向调试控制台或集成终端输出特定消息时在网页浏览器中打开一个URL。详情请参阅下面的调试服务器程序时自动打开URI部分。
许多调试器支持以下一些属性:
program
- 启动调试器时要运行的可执行文件或文件args
- 传递给程序以进行调试的参数env
- 环境变量(值null
可以用来“取消定义”一个变量)envFile
- 包含环境变量的dotenv文件的路径cwd
- 用于查找依赖项和其他文件的当前工作目录port
- 连接到正在运行的进程时的端口stopOnEntry
- 程序启动时立即中断console
- 使用哪种类型的控制台,例如,internalConsole
、integratedTerminal
或externalTerminal
变量替换
VS Code 将常用路径和其他值作为变量提供,并支持在 launch.json
中的字符串内进行变量替换。这意味着您不必在调试配置中使用绝对路径。例如,${workspaceFolder}
提供工作区文件夹的根路径,${file}
提供活动编辑器中打开的文件,${env:Name}
提供环境变量 'Name'。
你可以在变量参考中查看预定义变量的完整列表,或者在launch.json
字符串属性中调用IntelliSense来查看。
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/app.js",
"cwd": "${workspaceFolder}",
"args": ["${env:USERNAME}"]
}
平台特定属性
Launch.json
支持定义依赖于调试器运行的操作系统的值(例如,传递给程序的参数)。为此,请将特定平台的文字放入 launch.json
文件中,并在该文字内指定相应的属性。
以下是一个在Windows上以不同方式传递"args"
给程序的示例:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/node_modules/gulp/bin/gulpfile.js",
"args": ["myFolder/path/app.js"],
"windows": {
"args": ["myFolder\\path\\app.js"]
}
}
]
}
有效的操作系统属性是"windows"
用于Windows,"linux"
用于Linux,以及"osx"
用于macOS。在特定操作系统范围内定义的属性会覆盖在全局范围内定义的属性。
请注意,type
属性不能放在特定平台的部分中,因为在远程调试场景中,type
间接决定了平台,这将导致循环依赖。
在下面的示例中,调试程序总是在入口处停止,除了在macOS上:
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/node_modules/gulp/bin/gulpfile.js",
"stopOnEntry": true,
"osx": {
"stopOnEntry": false
}
}
]
}
全局启动配置
VS Code 支持在您的用户设置中添加一个"launch"
对象。这个"launch"
配置随后将在您的工作区之间共享。例如:
"launch": {
"version": "0.2.0",
"configurations": [{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${file}"
}]
}
高级断点主题
条件断点
VS Code 的一个强大调试功能是能够根据表达式、命中次数或两者的组合来设置条件。
- 表达式条件: 当表达式评估为
true
时,断点将被触发。 - 命中次数: 命中次数控制断点在被触发多少次后才会中断执行。是否遵循命中次数以及表达式的确切语法可能因调试器扩展而异。
在创建源断点时(使用添加条件断点操作)或修改现有断点时(使用编辑条件操作),您可以添加条件和/或命中计数。在这两种情况下,都会打开一个带有下拉菜单的内联文本框,您可以在其中输入表达式:
条件和命中次数编辑支持也适用于函数和异常断点。 您可以从上下文菜单或新的内联编辑条件操作启动条件编辑。
在BREAKPOINTS视图中进行条件编辑的示例:
如果调试器不支持条件断点,则添加条件断点和编辑条件操作不可用。
触发的断点
触发的断点是在另一个断点被命中后自动启用的断点。在诊断仅在特定前提条件下发生的代码故障时,它们非常有用。
可以通过右键单击符号边距,选择添加触发断点,然后选择启用该断点的其他断点来设置触发断点。
触发的断点适用于所有语言,条件断点也可以用作触发器。
内联断点
内联断点仅在执行到达与内联断点关联的列时才会触发。这在调试包含单行多个语句的压缩代码时特别有用。
可以使用⇧F9 (Windows, Linux Shift+F9)或在调试会话期间通过上下文菜单设置内联断点。内联断点在编辑器中以内联方式显示。
内联断点也可以有条件。可以通过编辑器左边距中的上下文菜单编辑一行上的多个断点。
函数断点
与直接在源代码中放置断点不同,调试器可以支持通过指定函数名称来创建断点。这在源代码不可用但函数名称已知的情况下非常有用。
通过按下BREAKPOINTS部分标题中的+按钮并输入函数名称来创建函数断点。函数断点在BREAKPOINTS部分中以红色三角形显示。
数据断点
如果调试器支持数据断点,可以从VARIABLES视图的上下文菜单中设置它们。Break on Value Change/Read/Access命令添加一个数据断点,当基础变量的值被更改/被读取/被访问时触发。数据断点在BREAKPOINTS部分中以红色六边形显示。
调试控制台 REPL
表达式可以通过调试控制台 REPL(读取-求值-打印循环)功能进行评估。要打开调试控制台,请使用调试窗格顶部的调试控制台操作或使用视图:调试控制台命令(⇧⌘Y (Windows, Linux Ctrl+Shift-Y))。
表达式在您按下Enter后进行评估,调试控制台REPL在您输入时显示建议。如果您需要输入多行,请在行之间使用Shift+Enter,然后使用Enter发送所有行进行评估。
调试控制台输入使用活动编辑器的模式,这意味着调试控制台输入支持语法着色、缩进、引号自动关闭和其他语言特性。
注意: 您必须处于正在运行的调试会话中才能使用调试控制台REPL。
将输入/输出重定向到/从调试目标
重定向输入/输出是调试器/运行时特定的,因此VS Code没有适用于所有调试器的内置解决方案。
以下是您可能想要考虑的两种方法:
-
在终端或命令提示符中手动启动程序以进行调试(“调试目标”),并根据需要重定向输入/输出。确保将适当的命令行选项传递给调试目标,以便调试器可以附加到它。创建并运行一个“附加”调试配置,该配置附加到调试目标。
-
如果您使用的调试器扩展可以在VS Code的集成终端(或外部终端)中运行调试目标,您可以尝试将shell重定向语法(例如,"<" 或 ">")作为参数传递。
这是一个
launch.json
配置的示例:{ "name": "launch program that reads a file from stdin", "type": "node", "request": "launch", "program": "program.js", "console": "integratedTerminal", "args": ["<", "in.txt"] }
这种方法要求“<”语法通过调试器扩展传递,并在集成终端中保持未修改。
多目标调试
对于涉及多个进程的复杂场景(例如,客户端和服务器),VS Code 支持多目标调试。在启动第一个调试会话后,您可以启动另一个调试会话。一旦第二个会话启动并运行,VS Code 用户界面将切换到多目标模式:
-
各个会话现在显示为CALL STACK视图中的顶级元素。
-
调试工具栏显示当前活动会话(所有其他会话可在下拉菜单中找到)。
-
调试操作(例如,调试工具栏中的所有操作)都在活动会话上执行。可以通过使用调试工具栏中的下拉菜单或在调用堆栈视图中选择不同的元素来更改活动会话。
复合启动配置
启动多个调试会话的另一种方法是使用复合启动配置。您可以在launch.json
文件中的compounds
属性中定义复合启动配置。使用configurations
属性列出应并行启动的两个或多个启动配置的名称。可以选择指定一个preLaunchTask
,该任务在启动各个调试会话之前运行。布尔标志stopAll
控制手动终止一个会话是否会停止所有复合会话。
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Server",
"program": "${workspaceFolder}/server.js"
},
{
"type": "node",
"request": "launch",
"name": "Client",
"program": "${workspaceFolder}/client.js"
}
],
"compounds": [
{
"name": "Server/Client",
"configurations": ["Server", "Client"],
"preLaunchTask": "${defaultBuildTask}",
"stopAll": true
}
]
}
复合启动配置显示在启动配置下拉菜单中。
远程调试
VS Code 不支持所有语言的内置远程调试。远程调试是您使用的调试扩展的功能,您应该查阅扩展在 Marketplace 中的页面以获取支持和详细信息。
然而,有一个例外:VS Code 中包含的 Node.js 调试器支持远程调试。请参阅 Node.js 调试 主题,了解如何配置此功能。
调试服务器程序时自动打开URI
开发一个网页程序通常需要在网页浏览器中打开一个特定的URL,以便在调试器中触发服务器代码。VS Code 有一个内置功能“serverReadyAction”来自动化这项任务。
这是一个简单的Node.js Express应用程序示例:
var express = require('express');
var app = express();
app.get('/', function(req, res) {
res.send('Hello World!');
});
app.listen(3000, function() {
console.log('Example app listening on port 3000!');
});
此应用程序首先为“/”URL安装一个“Hello World”处理程序,然后开始在端口3000上监听HTTP连接。端口在调试控制台中宣布,通常,开发人员现在会在他们的浏览器应用程序中输入http://localhost:3000
。
serverReadyAction 功能使得可以向任何启动配置添加一个结构化属性 serverReadyAction
,并选择要执行的“操作”:
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/app.js",
"serverReadyAction": {
"pattern": "listening on port ([0-9]+)",
"uriFormat": "http://localhost:%s",
"action": "openExternally"
}
}
这里的pattern
属性描述了用于匹配程序输出字符串的正则表达式,该字符串宣布了端口。端口号的模式被放在括号中,以便它作为正则表达式捕获组可用。在这个例子中,我们只提取端口号,但也可以提取完整的URI。
uriFormat
属性描述了端口号如何转换为 URI。第一个 %s
由匹配模式的第一个捕获组替换。
生成的URI随后会在VS Code外部(“外部”)使用为该URI方案配置的标准应用程序打开。
通过Edge或Chrome触发调试
或者,可以将action
设置为debugWithEdge
或debugWithChrome
。在这种模式下,可以添加一个webRoot
属性,该属性将传递给Chrome或Edge调试会话。
为了简化一些事情,大多数属性是可选的,我们使用以下回退值:
- pattern:
"listening on.* (https?://\\S+|[0-9]+)"
匹配常用的消息 "listening on port 3000" 或 "Now listening on: https://localhost:5001"。 - uriFormat:
"http://localhost:%s"
- webRoot:
"${workspaceFolder}"
触发任意启动配置
在某些情况下,您可能需要为浏览器调试会话配置其他选项,或者完全使用不同的调试器。您可以通过将action
设置为startDebugging
,并将name
属性设置为启动配置的名称来实现这一点,当pattern
匹配时启动该配置。
命名的启动配置必须与包含serverReadyAction
的文件或文件夹位于同一位置。
这里展示了serverReadyAction功能的实际应用:
下一步
要了解VS Code的Node.js调试支持,请查看:
- Node.js - 描述包含在VS Code中的Node.js调试器。
- TypeScript - Node.js 调试器也支持 TypeScript 调试。
要查看调试基础教程,请观看此视频:
- Getting started with debugging in VS Code - 了解如何在VS Code中进行调试。
要了解通过VS Code扩展对其他编程语言的调试支持:
要了解VS Code的任务运行支持,请访问:
- Tasks - 描述如何使用Gulp、Grunt和Jake运行任务,以及如何显示错误和警告。
要编写自己的调试器扩展,请访问:
- Debugger Extension - 使用一个模拟示例来说明创建 VS Code 调试扩展所需的步骤。
常见问题
支持的调试场景有哪些?
基于Node.js的应用程序的调试在Linux、macOS和Windows上开箱即用地支持VS Code。许多其他场景由VS Code扩展在市场中提供支持。
我在运行和调试视图的下拉菜单中没有看到任何启动配置。出了什么问题?
最常见的问题是你没有设置launch.json
,或者该文件中存在语法错误。另外,你可能需要打开一个文件夹,因为无文件夹调试不支持启动配置。