配置C#调试

你可以在Visual Studio Code中使用launch.jsonlaunchSettings.json或你的用户settings.json文件来配置C#调试器。

以下是调试时您可能想要更改的常见选项。

配置 VS Code 的调试行为

预启动任务

preLaunchTask 字段在调试程序之前运行 tasks.json 中的关联任务名称。您可以通过从 VS Code 命令面板执行命令 Tasks: Configure Tasks Runner 来获取默认的构建预启动任务。

这将创建一个运行dotnet build的任务。你可以在VS Code的任务文档中阅读更多信息。

可用性

  • launch.json ✔️
  • settings.json
  • launchSettings.json

程序

程序字段设置为要启动的应用程序dll或.NET Core主机可执行文件的路径。

此属性通常采用以下形式:"${workspaceFolder}/bin/Debug//"。

示例:"${workspaceFolder}/bin/Debug/netcoreapp1.1/MyProject.dll"

其中:

  • 是调试项目所构建的框架。这通常在项目文件中作为 'TargetFramework' 属性找到。
  • 是被调试项目的构建输出dll的名称。这通常与项目文件名相同,但带有'.dll'扩展名。

可用性

  • launch.json ✔️
  • settings.json
  • launchSettings.json ✔️ 作为 executablePath

当前工作目录

目标进程的工作目录。

可用性

  • launch.json ✔️
  • settings.json
  • launchSettings.json ✔️ 作为 workingDirectory

参数

这些是将传递给您的程序的参数。

可用性

  • launch.json ✔️
  • settings.json
  • launchSettings.json ✔️ 作为 commandLineArgs

在入口处停止

如果你需要在目标的入口点停止,你可以选择将stopAtEntry设置为"true"。

可用性

  • launch.json ✔️
  • settings.json ✔️ 作为 csharp.debug.stopAtEntry
  • launchSettings.json

启动网页浏览器

默认的launch.json模板(截至C#扩展v1.20.0)用于ASP.NET Core项目,使用以下配置来使VS Code在ASP.NET启动时启动一个网页浏览器:

    "serverReadyAction": {
        "action": "openExternally",
        "pattern": "\\bNow listening on:\\s+(https?://\\S+)"
    }

关于此的注意事项:

  1. 如果你希望浏览器自动启动,你可以直接删除这个元素(如果你的launch.json中有launchBrowser元素,也可以删除它)。

  2. 此模式使用ASP.NET Core写入控制台的URL启动网络浏览器。如果您想修改URL,请参阅指定浏览器的URL。如果目标应用程序在另一台机器或容器上运行,或者applicationUrl具有特殊的主机名(例如:"applicationUrl": "http://*:1234/"),这可能很有用。

  3. serverReadyAction 是 VS Code 的一个新功能。它比 C# 扩展调试器中内置的旧功能 launchBrowser 更受推荐,因为它可以在 C# 扩展在远程机器上运行时工作,它使用为 VS Code 配置的默认浏览器,并且还允许使用脚本调试器。如果这些功能对你来说都不重要,你可以继续使用 launchBrowser。如果你想要运行特定程序而不是启动默认浏览器,你也可以继续使用 launchBrowser

  4. 更多关于serverReadyAction的文档可以在Visual Studio Code 2019年2月发布说明中找到。

  5. 这种方式的工作原理是VS Code会抓取输出到控制台的内容。如果某一行匹配了模式,它就会针对被模式“捕获”的URL启动浏览器。

    以下是该模式的解释:

    • \\b : Matches on a word boundary. Note that \b indicates a word boundary, but because this is in a json string, the \ needs to be escaped, hence \\b.
    • Now listening on: : This is a string literal, meaning that the next text must be Now listening on:.
    • \\s+ : Matches one or more space characters.
    • ( : This is the beginning of a 'capture group'. This indicates the region of text to be saved and used to launch the browser.
    • http : String literal.
    • s? : Either the character s or nothing.
    • :// : String literal.
    • \\S+ : One or more nonwhitespace characters.
    • ) : The end of the capture group.
  6. 两种形式的浏览器启动都需要"console": "internalConsole",因为浏览器启动器会抓取目标进程的标准输出来了解Web服务器何时初始化完成。

指定浏览器的URL

如果你想忽略控制台输出中的URL,你可以从模式中移除(),并将uriFormat设置为你想要启动的内容。

示例:

    "serverReadyAction": {
        "action": "openExternally",
        "pattern": "\\bNow listening on:\\s+https?://\\S",
        "uriFormat": "http://localhost:1234"
    }

如果你想使用控制台输出中的端口号,而不是主机名,你也可以使用类似这样的方法:

    "serverReadyAction": {
        "action": "openExternally",
        "pattern": "\\bNow listening on:\\s+http://\\S+:([0-9]+)",
        "uriFormat": "http://localhost:%s"
    }

事实上,你可以打开几乎任何URL,例如你可以通过这样做来打开默认的swagger ui:

    "serverReadyAction": {
        "action": "openExternally",
        "pattern": "\\bNow listening on:\\s+http://\\S+:([0-9]+)",
        "uriFormat": "http://localhost:%s/swagger/index.html"
    }

注意 你需要确保你的项目已经设置了swaggerui才能进行此操作。

可用性

  • launch.json ✔️
  • settings.json
  • launchSettings.json ✔️ 带有 launchBrowserapplicationUrl

环境变量

环境变量可以通过以下模式传递到您的程序中:

    "env": {
        "myVariableName":"theValueGoesHere"
    }

可用性

  • launch.json ✔️
  • settings.json
  • launchSettings.json ✔️ 作为 environmentVariables

控制台(终端)窗口

"console" 设置控制目标应用程序启动时使用的控制台(终端)窗口。它可以设置为以下任一值 --

  • "internalConsole"(默认):目标进程的控制台输入(stdin)和输出(stdout/stderr)通过VS Code调试控制台进行路由。这种模式的优点是它允许您在一个地方查看来自调试器和目标程序的消息,因此您不会错过重要消息或需要来回切换。这对于具有简单控制台交互的程序非常有用(例如:使用Console.WriteLine和/或Console.ReadLine)。当目标程序需要完全控制控制台时,不应使用此模式,例如需要更改光标位置、使用Console.ReadKey进行输入等的程序。有关如何输入到控制台的说明,请参见下文。
  • "integratedTerminal" : 目标进程将在VS Code的集成终端中运行。选择编辑器下方标签组中的终端标签与您的应用程序进行交互。使用此模式时,默认情况下,启动调试时不会显示调试控制台。如果使用launch.json,可以通过internalConsoleOptions进行配置。
  • "externalTerminal": 目标进程将在其自己的外部终端中运行。使用此模式时,您需要在 Visual Studio Code 和外部终端窗口之间切换焦点。

可用性

  • launch.json ✔️
  • settings.json ✔️ 作为 csharp.debug.console
  • launchSettings.json

注意: csharp.debug.console 设置仅用于通过 dotnet 调试配置类型启动的控制台项目。

在使用internalConsole时将文本输入目标进程

当使用internalConsole时,您可以在Visual Studio Code中输入文本,这些文本将从Console.ReadLine和类似的从stdin读取的API中返回。为此,在程序运行时,在调试控制台底部的输入框中输入文本。按下Enter键将发送文本到目标进程。请注意,如果您在调试器下停止程序时在此框中输入文本,此文本将被评估为C#表达式,而不是发送到目标进程。

示例:

向控制台输入文本以设置为目标进程的标准输入的示例

launchSettings.json 支持

除了launch.json之外,启动选项还可以通过launchSettings.json文件进行配置。launchSettings.json的优势在于它允许在Visual Studio Code、完整的Visual Studio和dotnet run之间共享设置。

要配置使用哪个launchSettings.json配置文件(或防止其被使用),请设置launchSettingsProfile选项:

    "launchSettingsProfile": "ProfileNameGoesHere"

例如,这将使用来自此示例 launchSettings.json 文件的 myVariableName

{
  "profiles": {
    "ProfileNameGoesHere": {
      "commandName": "Project",
      "environmentVariables": {
        "myVariableName": "theValueGoesHere"
      }
    }
  }
}

如果未指定launchSettingsProfile,则将使用第一个具有"commandName": "Project"的配置文件。

如果 launchSettingsProfile 设置为 null 或空字符串,则 Properties/launchSettings.json 将被忽略。

默认情况下,调试器将在 {cwd}/Properties/launchSettings.json 中搜索 launchSettings.json。要自定义此路径,请设置 launchSettingsFilePath

   "launchSettingsFilePath": "${workspaceFolder}/<Relative-Path-To-Project-Directory/Properties/launchSettings.json"

限制:

  1. 仅支持具有"commandName": "Project"的配置文件。
  2. 仅支持 environmentVariablesapplicationUrlcommandLineArgs 属性
  3. launch.json 中的设置将优先于 launchSettings.json 中的设置,因此,例如,如果 argslaunch.json 中已经设置为非空字符串/数组,则 launchSettings.json 的内容将被忽略。

可用性

  • launch.json ✔️
  • settings.json
  • launchSettings.json

源文件映射

你可以选择通过提供使用此形式的映射来配置源文件的打开方式:

    "sourceFileMap": {
        "C:\\foo":"/home/me/foo"
    }

在这个例子中:

  • C:\foo 是一个或多个源文件(例如:program.cs)在编译模块(例如:MyCode.dll)时的原始位置。它可以是一个包含源文件的目录,也可以是一个源文件的完整路径(例如:c:\foo\program.cs)。它不需要存在于运行 Visual Studio Code 的计算机上,或者如果你正在进行远程调试,也不需要存在于远程机器上。调试器从 .pdb(符号)文件中读取源文件的路径,并使用此映射转换路径。
  • /home/me/foo 是 Visual Studio Code 现在可以找到源文件的路径。

可用性

  • launch.json ✔️
  • settings.json ✔️ 作为 csharp.debug.sourceFileMap
  • launchSettings.json

仅我的代码

你可以选择通过将justMyCode设置为"false"来禁用它。当你尝试调试一个没有符号或已优化的库时,你应该禁用“仅我的代码”。

    "justMyCode":false

“仅我的代码”是一组功能,通过隐藏您可能正在使用的优化库(如.NET框架本身)的一些细节,使您更容易专注于调试您的代码。此功能最重要的子部分是——

  • 用户未处理的异常:在异常即将被框架捕获之前自动停止调试器
  • 仅我的代码单步执行:在单步执行时,如果框架代码回调到用户代码,自动停止。

可用性

  • launch.json ✔️
  • settings.json ✔️ 作为 csharp.debug.justMyCode
  • launchSettings.json

需要确切的来源

调试器要求pdb和源代码完全一致。要更改此设置并禁用源代码一致性的检查,请添加:

    "requireExactSource": false

可用性

  • launch.json ✔️
  • settings.json ✔️ 作为 csharp.debug.requireExactSource
  • launchSettings.json

进入属性和运算符

调试器默认情况下会跳过托管代码中的属性和运算符。在大多数情况下,这提供了更好的调试体验。要更改此设置并启用进入属性或运算符的功能,请添加:

    "enableStepFiltering": false

可用性

  • launch.json ✔️
  • settings.json ✔️ 作为 csharp.debug.enableStepFiltering
  • launchSettings.json

日志记录

您可以选择启用或禁用应记录到输出窗口的消息。日志记录字段中的标志包括:'exceptions'、'moduleLoad'、'programOutput'、'browserStdOut' 和 'consoleUsageMessage'。

在'logging.diagnosticsLog'下还有一些高级选项,用于诊断调试器的问题。

可用性

  • launch.json ✔️
  • settings.json ✔️ 在 csharp.debug.logging
  • launchSettings.json

管道传输

如果您需要使用另一个可执行文件在VS Code和.NET Core调试器后端(vsdbg)之间中继标准输入和输出,以便调试器连接到远程计算机,请按照以下模式添加pipeTransport字段:

    "pipeTransport": {
        "pipeProgram": "ssh",
        "pipeArgs": [ "-T", "ExampleAccount@ExampleTargetComputer" ],
        "debuggerPath": "~/vsdbg/vsdbg",
        "pipeCwd": "${workspaceFolder}",
        "quoteArgs": true
    }

有关管道传输的更多信息可以在这里找到。

你可以找到关于为Windows Subsystem for Linux (WSL)配置管道传输的信息这里

可用性

  • launch.json ✔️
  • settings.json
  • launchSettings.json

操作系统特定配置

如果有需要根据操作系统更改的特定命令,您可以使用以下字段:'windows'、'osx' 或 'linux'。您可以为特定的操作系统替换上述任何字段。

抑制JIT优化

.NET 调试器支持以下选项。如果为 true,当目标进程中加载了一个优化模块(在 Release 配置下编译的 .dll)时,调试器将要求即时编译器生成禁用优化的代码。该选项默认为 false。

    "suppressJITOptimizations": true

.NET中的优化工作原理: 如果你正在尝试调试代码,当代码优化时,调试会更容易。这是因为当代码被优化时,编译器和运行时会更改生成的CPU代码,使其运行得更快,但与原始源代码的映射关系不那么直接。这意味着调试器通常无法告诉你局部变量的值,代码单步执行和断点可能不会像你预期的那样工作。

通常,Release 构建配置会创建优化代码,而 Debug 构建配置则不会。Optimize MSBuild 属性控制是否告诉编译器优化代码。

在 .NET 生态系统中,代码从源代码转换为 CPU 指令的过程分为两步:首先,C# 编译器将您输入的文本转换为称为 MSIL 的中间二进制形式,并将其写入 .dll 文件。随后,.NET 运行时将此 MSIL 转换为 CPU 指令。这两个步骤都可以在一定程度上进行优化,但由 .NET 运行时执行的第二步优化更为显著。

该选项的作用是什么: 此选项控制在启用了优化的情况下编译的DLL加载到目标进程内时会发生什么。如果此选项为false(默认值),则当.NET运行时将MSIL代码编译为CPU代码时,它会保持优化启用。如果该选项为true,则调试器请求禁用优化。

何时应使用此选项: 当您从其他来源(如nuget包)下载了dlls,并且您想要调试此DLL中的代码时,应使用此选项。为了使此功能正常工作,您还必须找到此DLL的符号(.pdb)文件。

如果您只对调试本地构建的代码感兴趣,最好将此选项保持为false,因为在某些情况下,启用此选项会显著减慢调试速度。导致这种减慢的原因有两个——

  • 优化后的代码运行速度更快。如果你关闭了大量代码的优化,时间会累积起来。
  • 如果您启用了“仅我的代码”,调试器甚至不会尝试加载已优化的dll的符号。查找符号可能需要很长时间。

此选项的限制: 有两种情况下此选项将不会起作用:

1: 在将调试器附加到已经运行的进程的情况下,此选项对调试器附加时已经加载的模块没有影响。

2: 此选项对已预编译(ngen'ed)为本机代码的dlls没有影响。但是,您可以通过设置环境变量COMPlus_ReadyToRun0来禁用预编译代码的使用。如果您针对的是较旧版本的.NET Core(2.x),还需将COMPlus_ZapDisable设置为'1'。如果您在调试器下启动,可以通过将此设置添加到launch.json来配置此设置:

    "env": {
        "COMPlus_ZapDisable": "1",
        "COMPlus_ReadyToRun": "0"
    }

可用性

  • launch.json ✔️
  • settings.json ✔️ 作为 csharp.debug.suppressJITOptimizations
  • launchSettings.json

符号选项

symbolOptions 元素允许自定义调试器如何搜索符号。示例:

    "symbolOptions": {
        "searchPaths": [
            "~/src/MyOtherProject/bin/debug",
            "https://my-companies-symbols-server"
        ],
        "searchMicrosoftSymbolServer": true,
        "searchNuGetOrgSymbolServer": true,
        "cachePath": "/symcache",
        "moduleFilter": {
            "mode": "loadAllButExcluded",
            "excludedModules": [ "DoNotLookForThisOne*.dll" ]
        }
    }

属性

searchPaths: 符号服务器URL数组(例如:https://msdl.microsoft.com/download/symbols)或目录(例如:/build/symbols),用于搜索.pdb文件。除了默认位置、模块旁边和.pdb最初放置的路径之外,还将搜索这些目录。

searchMicrosoftSymbolServer: 如果为 true,则将 Microsoft 符号服务器 (https://msdl.microsoft.com/download/symbols) 添加到符号搜索路径中。如果未指定,此选项默认为 false

searchNuGetOrgSymbolServer: 如果为 true,则 Nuget.org 符号服务器 (https://symbols.nuget.org/download/symbols) 将被添加到符号搜索路径中。如果未指定,此选项默认为 false

cachePath": 从符号服务器下载的符号应缓存的目录。如果未指定,在Windows上调试器默认为 %TEMP%\\SymbolCache,在Linux和macOS上调试器默认为 ~/.dotnet/symbolcache

moduleFilter.mode: 此值为 "loadAllButExcluded""loadOnlyIncluded"。在 "loadAllButExcluded" 模式下,调试器会为所有模块加载符号,除非该模块在 'excludedModules' 数组中。在 "loadOnlyIncluded" 模式下,调试器不会尝试为任何模块加载符号,除非它在 'includedModules' 数组中,或者通过 'includeSymbolsNextToModules' 设置包含。

loadAllButExcluded 模式的属性

moduleFilter.excludedModules: 调试器不应加载符号的模块数组。支持通配符(例如:MyCompany.*.dll)。

loadOnlyIncluded 模式的属性

moduleFilter.includedModules: 调试器应加载符号的模块数组。支持通配符(例如:MyCompany.*.dll)。

moduleFilter.includeSymbolsNextToModules: 如果为true,对于不在'includedModules'数组中的任何模块,调试器仍将检查模块本身和启动可执行文件旁边的符号,但不会检查符号搜索列表中的路径。此选项默认为'true'。

可用性

  • launch.json ✔️
  • settings.json ✔️ 在 csharp.debug.symbolOptions
  • launchSettings.json

源链接是一项功能,它使得当您调试在另一台计算机上构建的代码时,例如来自nuget包的代码,调试器可以通过从网络下载来自动显示匹配的源代码。为了实现这一点,您正在调试的代码的.pdb文件包含将DLL中的源文件映射到调试器可以下载的URL的数据。有关源链接的更多信息可以在https://aka.ms/SourceLinkSpec找到。

launch.json 中的 sourceLinkOptions 元素允许通过 URL 自定义 Source Link 的行为。它是一个从 URL 到该 URL 的 Source Link 选项的映射。URL 名称中支持通配符。目前唯一的自定义选项是是否为该 URL 启用 Source Link,但未来可能会添加更多选项。

示例:

    "sourceLinkOptions": {
        "https://raw.githubusercontent.com/*": { "enabled": true },
        "*": { "enabled": false }
    }

此示例为GitHub URL启用源链接,并为所有其他URL禁用源链接。

此选项的默认值是启用所有URL的源链接。同样,对于sourceLinkOptions映射中没有规则的任何URL,也会启用源链接。

要禁用所有URL的Source Link,请使用"sourceLinkOptions": { "*": { "enabled": false } }

如果有多个条目覆盖相同的URL,则使用更具体的条目(字符串长度较长的条目)。

目前,Source Link 仅适用于无需身份验证即可访问的源文件。因此,例如,调试器可以从 GitHub 上的开源项目下载源文件,但不能从私有的 GitHub 仓库或 Visual Studio Team Services 下载。

可用性

  • launch.json ✔️
  • settings.json
  • launchSettings.json

目标架构选项 (macOS M1)

.NET 在 Apple M1 上支持 x86_64 和 ARM64。调试时,调试器附加到的进程的架构和调试器必须匹配。如果不匹配,可能会导致 Unknown Error: 0x80131c3c

扩展程序尝试根据PATH中dotnet --info的输出解析targetArchitecture,否则尝试使用与VS Code相同的架构。

你可以通过在launch.json中设置targetArchitecture来覆盖此行为。

示例:

    "targetArchitecture": "arm64"

可用性

  • launch.json ✔️
  • settings.json
  • launchSettings.json

检查 DevCert

此选项控制在启动时,调试器是否应检查计算机是否具有用于开发运行在https端点的Web项目的自签名HTTPS证书。为此,它会尝试运行dotnet dev-certs https --check --trust,如果未找到证书,它将提示用户建议创建一个。如果用户同意,扩展程序将运行dotnet dev-certs https --trust以创建受信任的自签名证书。

如果未指定,当设置了serverReadyAction时,默认为true。此选项在Linux、VS Code远程和VS Code网页版场景中无效。

你可以通过在launch.json中将checkForDevCert设置为false来覆盖此行为。

示例:

    "checkForDevCert": "false"

可用性

  • launch.json ✔️
  • settings.json
  • launchSettings.json ✔️ 作为 useSSL

配置 launchSettings.json

使用C# Dev Kit,您可以将launchSettings.json从Visual Studio带到Visual Studio Code中使用

示例:

{
  "iisSettings": {
    "windowsAuthentication": false,
    "anonymousAuthentication": true,
    "iisExpress": {
      "applicationUrl": "http://localhost:59481",
      "sslPort": 44308
    }
  },
  "profiles": {
    "EnvironmentsSample": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:7152;http://localhost:5105",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "EnvironmentsSample-Staging": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:7152;http://localhost:5105",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Staging",
        "ASPNETCORE_DETAILEDERRORS": "1",
        "ASPNETCORE_SHUTDOWNTIMEOUTSECONDS": "3"
      }
    },
    "EnvironmentsSample-Production": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "applicationUrl": "https://localhost:7152;http://localhost:5105",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Production"
      }
    },
    "IIS Express": {
      "commandName": "IISExpress",
      "launchBrowser": true,
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    }
  }
}

配置文件属性

  • commandLineArgs - 传递给正在运行的目标的参数。
  • executablePath - 可执行文件的绝对或相对路径。
  • workingDirectory - 设置命令的工作目录。
  • launchBrowser - 如果应该启动浏览器,则设置为true。
  • applicationUrl - 用于配置Web服务器的URL列表,以分号分隔。
  • sslPort - 用于网站的SSL端口。
  • httpPort - 用于网站的HTTP端口。

参见