ms_learn_csharp/033_Debug_console_apps_2/033_csharp.md

1070 lines
39 KiB
Markdown
Raw Normal View History

2024-08-18 00:26:35 -04:00
## Implement the Visual Studio Code debugging tools for C#
### Introduction
The faster you discover and identify bugs, the faster you can get your code
stabilized and released. Visual Studio Code supports code debugging for C# and
most other software development languages through the use of Extensions. Once
you've learned to use Visual Studio Code's debug tools, you'll spend less time
wondering why your code stopped working and more time developing great
applications.
Suppose you're using Visual Studio Code to develop a C# console application.
The primary purpose of the application is to process customer data based on
business rules. You develop the application using a small sample data set and
it runs without errors. However, when you run the code using the larger data
set, your code produces some unexpected results. You've read through the code
several times but it's difficult to find the errors in your logic. You've heard
that Visual Studio Code has good debugger tools, but you've never had to use
them. You can't waste any more time reading through the code. You decide that
learning the debugger tools is your best chance for completing the project on
time.
In this module, you learn how to effectively debug C# programs in Visual Studio
Code using breakpoints and other debugging tools, such as resources in the RUN
AND DEBUG view.
By the end of this module, you'll be able to configure and use the Visual Studio
Code debugger tools for C#.
#### Learning objectives
In this module, you will:
- Configure the Visual Studio Code debugger for a C# program.
- Create breakpoints and step through your code to isolate issues.
- Inspect your program state at any execution step.
- Use the call stack to find the source of an exception.
Ultimately, you'll be able to isolate code bugs efficiently using the debugger
tools, and you won't need to rely on `Console.WriteLine` anymore.
---
## Examine the Visual Studio Code debugger interface
The Visual Studio Code user interface provides several ways to configure debug
options and launch debug sessions.
### Debug features in the Visual Studio Code user interface
Visual Studio Code includes several user interface features that will help you
to configure, start, and manage debug sessions:
- Configure and launch the debugger: The Run menu and RUN AND DEBUG view can
both be used to configure and launch debug sessions.
- Examine application state: The RUN AND DEBUG view includes a robust interface
that exposes various aspects of your application state during a debug session.
- Runtime execution control: The Debug toolbar provides high-level runtime
controls during code execution.
> Note
> This Unit introduces you to a lot of debugging tools and terminology. Please
keep in mind that this is your first look at these tools, not your last. You'll
have an opportunity to complete hands-on activities with most of these tools
during this module. Try not to feel overwhelmed by the volume of information
that's presented.
---
### Run menu options
The Visual Studio Code Run menu provides easy access to some common run and
debug commands.
<div align="center">
![img](./img/code_oss_debuger.png)
</div>
The Run menu provides menu options that are grouped into six sections.
1. Start and stop applications. This section of the menu includes options for
starting and stopping code execution, with and without the debugger attached.
2. Launch configurations. This section of the menu provides access to examine
or create launch configurations.
3. Runtime control. This section of the menu enables the developer to control
how they want to advance through the code. Controls are enabled when execution
has paused during a debug session.
4. Set Breakpoints. This section of the menu enables the developer to set
breakpoints on code lines. Code execution pauses on Breakpoints during a debug
session.
5. Manage Breakpoints. This section of the menu enables the developer to manage
breakpoints in bulk rather than individually.
6. Install Debuggers. This section of the menu opens the Visual Studio Code
EXTENSIONS view filtered for code debuggers.
### Run and Debug view user interface
The RUN AND DEBUG view provides access to runtime tools that can be invaluable
during the debug process.
1. Run and Debug controls panel. Used to configure and start a debug session.
2. VARIABLES section. Used to view and manage variable state during a debug
session.
3. WATCH section. Used to monitor variables or expressions. For example, you
could configure an expression using one or more variables and watch it to see
when a particular condition is met.
4. CALL STACK section. Used to keep track of the current point of execution
within the running application, starting with the initial point of entry into
the application. The call stack shows which method is currently being executed,
as well as the method or methods in the execution path that led to the current
point of execution (current line of code).
5. BREAKPOINTS section. Displays the current breakpoint settings.
6. Debug toolbar. Used to control code execution during the debug process. This
toolbar is only displayed while the application is running.
7. Current execution step. Used to identify the current execution step by
highlighting it in the Editor. In this case, the current execution step is a
breakpoint (breakpoints are marked with a red dot to the left of the line
number).
8. DEBUG CONSOLE. Used to display messages from the debugger. The DEBUG CONSOLE
panel is the default console for console applications and is able to display
output from `Console.WriteLine()` and related `Console` output methods.
### Controls panel for the Run and Debug view
At the top of the RUN AND DEBUG view, you can find the launch controls:
<div align="center">
![img](./img/code_oss_debug_panel.png)
</div>
1. Start debugging. This button (a green arrow) is used to start a debug
session.
2. Launch configurations. This dropdown menu provides access to launch
configurations. The selected option is displayed.
3. Open 'launch.json'. This button (a gear shape) can be used to open the
`launch.json` file, where you can edit the launch configuration if needed.
4. Views and More Actions. This button (an ellipsis) enables you to show/hide
sections of the debug panel as well as the DEBUG CONSOLE panel.
### Debug toolbar
The Debug toolbar provides execution controls while your application is running.
<div align="center">
![img](./img/code_oss_debug_toolbar.png)
</div>
1. Pause/Continue. This button can be used to pause execution when the code is
running and Continue when code execution has been paused.
2. Step Over. This button can be used to execute the next method as a single
command without inspecting or following its component steps.
3. Step Into. This button can be used to enter the next method or code line and
observe line-by-line execution steps.
4. Step Out. When inside a method, this button can be used to return to the
earlier execution context by completing all remaining lines of the current
method as though they were a single command.
5. Restart. This button can be used to terminate the current program execution
and start debugging again using the current configuration.
6. Stop. This button can be used to terminate the current program execution.
In addition to six execution controls, the Debug toolbar provides a "handle" on
the left side that enables the developer to reposition the toolbar, and a "More"
dropdown on the right side that enables the developer to disconnect the
debugger.
> Note
> You can use the setting `debug.toolBarLocation` to control the location of
the debug toolbar. It can be floating (the default), docked to the RUN AND
DEBUG view, or hidden. A floating debug toolbar can be dragged horizontally and
down to the Editor area.
### Recap
Here are a few important things to remember from this unit:
The Visual Studio Code user interface can be used to configure, start, and
manage debug sessions. The launch.json file contains the launch configurations
for your application.
- The Run menu provides easy access to common run and debug commands grouped
into six sections.
- The RUN AND DEBUG view provides access to runtime tools, including the Run
and Debug controls panel. The sections of the RUN AND DEBUG view are VARIABLES,
WATCH, CALL STACK, and BREAKPOINTS.
- The Debug toolbar provides execution controls while your application is
running such as pause/continue, step over, step into, step out, restart and
stop.
- The DEBUG CONSOLE is used to display messages from the debugger. The DEBUG
CONSOLE can also display console output from your application.
---
## Exercise - Run code in the debug environment
The Visual Studio Code user interface enables developers to run their code in a
debug environment. Support for debugging is provided by extensions, and for C#
developers, debugger support is provided by the same extension that provides
support for code development and IntelliSense.
### Debugger and application interaction
A code debugger can be used to pause and resume code execution, examine
variable state, and even change the values assigned to variables at runtime.
You may be wondering, how can the debugger control and modify a running
application? The short answer is, the debugger has access to the application's
runtime environment and executable code.
> Note
> Debugger interaction with the runtime environment is an advanced topic. In
addition, understanding how the debugger works behind the scenes isn't a
requirement for using the debugger. However, the following description may
satisfy your curiosity.
The Visual Studio Code debugger for C# uses the .NET Core runtime to launch and
interact with an application. When you start the debugger, it creates a new
instance of the runtime and runs the application within that instance. The
runtime includes an application programming interface (API), which the debugger
uses to attach to the running process (your application).
Once your application is running and the debugger is attached, the debugger
communicates with the running process using the .NET Core runtime's debugging
APIs and a standard debug protocol. The debugger can interact with the process
(the application running within the .NET runtime instance) by setting
breakpoints, stepping through code, and inspecting variables. Visual Studio
Code's debugger interface enables you to navigate the source code, view call
stacks, and evaluate expressions.
The most common way to specify a debug session is a launch configuration in the
launch.json file. This approach is the default option enabled by the debugger
tools. For example, if you create a C# console application and select Start
Debugging from the Run menu, the debugger uses this approach to launch, attach
to, and then interact with your application.
### Create a new code project
The first step in learning the debugger tools is creating a code project that
you can run in the debugger.
- Open a new instance of Visual Studio Code.
- On the File menu, select **Open Folder**.
- On the Open Folder dialog, navigate to your folder.
- On the Open Folder dialog, select New folder.
- Name the new folder **Debug101**, and then select **Select Folder**.
- On the **Terminal** menu, select **New Terminal**.
A .NET CLI command can be used to create a new console app.
- At the TERMINAL panel command prompt, enter the following command:
```pwsh
dotnet new console
```
- Close the TERMINAL panel.
### Examine launch configurations for debugging
Visual Studio Code uses a launch configuration file to specify the application
that runs in the debug environment.
If the Debug101 folder doesn't include a Debug101.sln file, select `Program.cs`,
and then verify that a .sln file is created.
Opening a C# code file prompts the environment to check for project files. The
.sln file is a solution file that is used by Visual Studio to manage projects
and is usually created automatically when you create a new project in Visual
Studio Code. The .sln file is used by the debugger to identify the project that
should be run in the debug environment.
On the View menu, select **Command Palette**.
At the command prompt, enter .net: g and then select **`.NET: Generate Assets for
Build and Debug`**.
Notice the new `.vscode` folder that has been added to your project folder.
The `.vscode` folder contains files that are used to configure the debug
environment.
Expand the `.vscode` folder, and then select the launch.json file.
Take a minute to examine the launch.json file.
The launch configurations file can include multiple configurations. Each
configuration includes a collection of attributes that are used to define that
configuration.
Notice that the `prelaunchTask` attribute specifies a build task.
In the `.vscode` folder, select **`tasks.json`**.
Notice that the tasks.json file contains the *build* task for your code
project.
Close the `launch.json` and `tasks.json` files.
You take a closer look at the launch configuration attributes later in this
module.
### Run your code from the Run menu
The Run menu in Visual Studio Code provides the option to run your code with or
without the debugger.
Open the Program.cs file.
Replace the contents of your Program.cs file with the following code:
```cs
// This code uses a names array and corresponding methods to display
// greeting messages
string[] names = new string[] { "Sophia", "Andrew", "AllGreetings" };
string messageText = "";
foreach (string name in names) {
if (name == "Sophia")
messageText = SophiaMessage();
else if (name == "Andrew")
messageText = AndrewMessage();
else if (name == "AllGreetings")
messageText = SophiaMessage();
messageText = messageText + "\n\r" + AndrewMessage();
Console.WriteLine(messageText + "\n\r");
}
bool pauseCode = true;
while (pauseCode == true);
static string SophiaMessage() {
return "Hello, my name is Sophia.";
}
static string AndrewMessage() {
return "Hi, my name is Andrew. Good to meet you.";
}
```
On the **File** menu, select **Save**.
Open the **Run** menu.
Notice that the **Run** menu provides options for running your code with or
without debugging.
On the **Run** menu, select **Run Without Debugging**
Notice that the DEBUG CONSOLE panel displays console output, and that the
**Debug toolbar** displays execution controls.
The DEBUG CONSOLE panel should be displayed below the code Editor. By default,
the **Debug toolbar** (the small toolbar displaying code execution controls) is
located above the code Editor and horizontally centered on the Visual Studio
Code window.
On the **Debug toolbar**, select **Stop**.
### Start a debug session from the Run menu
The Run menu includes the option to start a debug session.
On the **Run** menu, select **Start Debugging**
Take a minute to review the messages displayed in the DEBUG CONSOLE panel.
The output from your application is the same as when you ran without debugging,
but other messages related to preparing the debug environment are displayed.
Notice the messages about loading .NET resources and your Debug101 application.
The first two messages report loading the .NET Core library and then your
Debug101 application.
```txt
Loaded 'C:\Program Files\dotnet\shared\Microsoft.NETCore.App\7.0.4\System.Private.CoreLib.dll'. Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Loaded 'C:\Users\someuser\Desktop\Debug101\bin\Debug\net7.0\Debug101.dll'. Symbols loaded.
```
The debugger uses a special instance of the .NET runtime to control the
execution of your application and evaluate application state.
On the Debug toolbar, select Stop.
### Run your code from the Run and Debug view
The RUN AND DEBUG view in Visual Studio Code supports a rich debugging
experience.
Switch to the RUN AND DEBUG view.
<div align="center">
![img](./img/code_oss_debug_01.png)
</div>
In the RUN AND DEBUG view, select Start Debugging.
The **Start Debugging** button is the green arrow on the control panel at the
top of the view.
Notice that the DEBUG CONSOLE panel shows the same messages about configuring
the debugger that were displayed when starting a debug process from the **Run**
menu.
On the **Debug toolbar**, select **Stop**.
### Examine the output from your application
Before closing the DEBUG CONSOLE panel, take a minute to review the output that
your code produced.
Notice that Andrew's greeting message is repeated unexpectedly.
During the remainder of this module, you'll use the Visual Studio Code debugger
tools to investigate coding issues.
### Recap
Here are a few important things to remember from this unit:
- The Visual Studio Code debugger for C# uses the .NET Core runtime to launch and interact with an application.
- The Visual Studio Code Run menu has options to start an application with and without the debugger attached.
- The Debug toolbar includes a button to Stop a running process.
- The RUN AND DEBUG view includes an option to start debugging an application.
---
## Examine breakpoint configuration options
Debuggers are used to help you to analyze your code and can be used to control
your program's runtime execution. When you start the Visual Studio Code
debugger, it immediately begins executing your code. Because your code executes
in micro-seconds, effective code debugging depends on your ability to pause the
program on any statement within your code. Breakpoints are used to specify
where code execution pauses.
### Set breakpoints
Visual Studio Code provides several ways to configure breakpoints in your code.
For example:
- Code Editor: You can set a breakpoint in the Visual Studio Code Editor by
clicking in the column to the left of a line number.
- Run menu: You can toggle a breakpoint on/off from the Run menu. The current
code line in the Editor specifies where the Toggle Breakpoint action is applied.
When a breakpoint is set, a red circle is displayed to the left of the line
number in the Editor. When you run your code in the debugger, execution pauses
at the breakpoint.
<div align="center">
![img](./img/code_oss_debug_02.png)
</div>
### Remove, disable, and enable breakpoints
After setting breakpoints in your application and using them to isolate an
issue, you may want to remove or disable the breakpoints.
To remove a breakpoint, repeat the action used to set a breakpoint. For example,
click the red circle to the left of the line number or use the toggle
breakpoint option on the Run menu.
What if you want to keep a breakpoint location, but you don't want it to
trigger during your next debug session? Visual Studio Code enables you to
"disable" a breakpoint rather than removing it altogether. To disable an active
breakpoint, right-click the red dot to the left of the line number, and then
select Disable Breakpoint from the context menu.
<div align="center">
![img](./img/code_oss_debug_03.png)
</div>
When you disable a breakpoint, the red dot to the left of the line number is
changed to a grey dot.
> Note
> The context menu that appears when you right-click a breakpoint also includes
the options to **Remove Breakpoint (Delete)** and **Edit Breakpoint**. The
**Edit Breakpoint** option is examined in the **Conditional breakpoints
Logpoints** section later in this unit.
In addition to managing individual breakpoints in the Editor, the **Run** menu
provides options for performing bulk operations that act on all breakpoints:
- **Enable All Breakpoints**: Use this option to enable all disabled breakpoints.
- **Disable All Breakpoints**: Use this option to disable all breakpoints.
- **Remove All Breakpoints**: Use this option to remove all breakpoints (both
enabled and disabled breakpoints are removed).
### Conditional breakpoints
A conditional breakpoint is a special type of breakpoint that only triggers
when a specified condition is met. For example, you can create a conditional
breakpoint that pauses execution when a variable named `numItems` is greater
than 5.
You've already seen that right-clicking a breakpoint opens a context menu that
includes the **Edit Breakpoint** option. Selecting **Edit Breakpoint** enables
you to change a standard breakpoint into a conditional breakpoint.
<div align="center">
![img](./img/code_oss_debug_04.png)
</div>
In addition to editing an existing breakpoint, you can also set a conditional
breakpoint directly. If you right-click (rather than left-click) to set a new
breakpoint, you can choose to create a conditional breakpoint.
When you create a conditional breakpoint, you need to specify an expression
that represents the condition.
Each time the debugger encounters the conditional breakpoint, it evaluates the
expression. If the expression evaluates as `true`, the breakpoint is triggered
and execution pauses. If the expression evaluates as `false`, execution
continues as if there was no breakpoint.
For example, suppose you need to debug some code that's inside the code block
of a `for` loop. You've noticed that the issue you're debugging only occurs
after the loop has completed several iterations. You decide that you want the
breakpoint to trigger once the loop's iteration control variable, `i`, is
greater than three. You create a conditional breakpoint and specify the
expression `i > 3`.
<div align="center">
![img](./img/code_oss_debug_05.png)
</div>
When you run your code in the debugger, it skips over your breakpoint until the
iteration when `i > 3` evaluates as true. When `i = 4`, execution pauses on
your conditional breakpoint.
### Support for `Hit Count` breakpoints and `Logpoints`
The C# debugger for Visual Studio Code also supports `Hit Count` breakpoints
and `Logpoints`.
A 'hit count' breakpoint can be used to specify the number of times that a
breakpoint must be encountered before it will 'break' execution. You can
specify a hit count value when creating a new breakpoint (with the Add
Conditional Breakpoint action) or when modifying an existing one (with the Edit
Condition action). In both cases, an inline text box with a dropdown menu opens
where you can enter the hit count value.
A 'Logpoint' is a variant of a breakpoint that does not "break" into the
debugger but instead logs a message to the console. Logpoints are especially
useful for injecting logging while debugging production environments that
cannot be paused or stopped. A Logpoint is represented by a "diamond" shaped
icon rather than a filled circle. Log messages are plain text but can include
expressions to be evaluated within curly braces `{}`
Logpoints can include a conditional 'expression' and/or 'hit count' to further
control when logging messages are generated. For example, you can combine a
Logpoint message of `i = {i}` with Hit Count condition `>4` to generate log
messages as follows:
### Recap
Here are a few important things to remember from this unit:
- Visual Studio Code enables setting breakpoints in the code editor or from the
**Run menu**. Breakpoint code lines are marked with a red dot to the left of the
line number.
- Breakpoints can be removed or disabled using the same options used to set
them. Bulk operations that affect all breakpoints are available on the **Run**
menu.
- Conditional breakpoints can be used to pause execution when a specified
condition is met or when a 'hit count' is reached.
- Logpoints can be used to log information to the terminal without pausing
execution or inserting code.
---
## Exercise
### Set breakpoints
Breakpoints are used during the debug process pause execution. This enables you
to track variables and examine the sequence in which your code is executed.
Breakpoints are a great way to start your debug process.
### Set a breakpoint
Earlier in this module you completed an exercise where you ran an application
in the debugger. The application displayed "greeting messages" in the DEBUG
CONSOLE panel. At the end of the exercise, you noticed that the code repeats
Andrew's greeting in an unexpected way.
In this exercise, you'll use a breakpoint to help you identify the issue.
Ensure that your Program.cs file contains the following code sample:
```cs
//This code uses a names array and corresponding methods to display
//greeting messages
string[] names = new string[] { "Sophia", "Andrew", "AllGreetings" };
string msg_txt = "";
foreach (string name in names) {
if (name == "Sophia") {
msg_txt = sophia_msg();
} else if (name == "Andrew") {
msg_txt = andrew_msg();
} else if { (name == "AllGreetings")
msg_txt = sophia_msg();
msg_txt = msg_txt + "\n\r" + andrew_msg();
}
Console.WriteLine(msg_txt + "\n\r");
}
bool pause_code = true;
while (pause_code == true);
static string sophia_msg() {
return "Hello, my name is Sophia.";
}
static string andrew_msg() {
return "Hi, my name is Andrew. Good to meet you.";
}
```
Use the Visual Studio Code debugger tools to set a breakpoint on the first code
line inside the foreach loop.
> Tip
> One easy option for toggling on/off a breakpoint is to select (left-click)
the area to the left of the line number. Breakpoints can also be set by using
the Run menu and by using keyboard shortcuts.
On the **Run** menu, select **Start Debugging**.
Notice that code execution pauses at the breakpoint, and that the current code
line is highlighted in the Editor.
On the Debug controls toolbar, select Step Into.
You can hover the mouse pointer over the buttons on the **Debug controls**
toolbar to display the button labels.
Notice that code execution advances to the following code line and pauses:
```cs
messageText = SophiaMessage();
```
This code line assigns the return value of the `sophia_msg` method to the
string variable `messageText`.
Take a moment to consider why selecting **Step Into** produced this result.
- The **Step Into** button is used to advance to the next executable statement.
- Since the first element in the `names` array is `Sophia` and the `if`
statement is checking for the name `Sophia`, the expression evaluates to `true`
and code execution moves into the code block of the `if` statement.
On the **Debug controls** toolbar, select **Step Into**.
Notice that code execution advances to the `sophia_msg` method and pauses.
The **Step Into** button has advanced to the next executable code line. The
next executable code line isn't the next line number in the file, it's the next
statement in the execution path. In this case, the next executable statement is
the entry point to the `sophia_msg` method.
On the **Debug controls** toolbar, select Step **Out**.
Notice that code execution returns to the code line that called the
`sophia_msg` method and pauses.
Take a moment to consider why selecting **Step Out** produced this result.
When inside a method, the **Step Out** button completes the remaining lines of
the current method and then returns to the execution context that invoked the
method.
On the **Debug controls** toolbar, select **Step Into**.
Notice that code execution advances to the following code line and pauses:
```cs
messageText = messageText + "\n\r" + AndrewMessage();
```
Take a moment to consider why execution advanced to this code line.
Although the code indentation implies that this code line is part of the code
block for the `else if` statement, it isn't. Using curly braces `{}` to define
the code blocks for this `if - else if` structure would have helped to avoid
this bug. As the code is written, Andrew's message will be added to `msg_txt`
each time the loop iterates.
### Verify your code updates
Once you've isolated an issue in your code, you should update your code and
then verify that the issue has been fixed.
On the **Debug controls** toolbar, select **Stop**.
Take a minute to fix your code logic.
You have a few options for fixing the identified issue in your code. For
example:
- You could keep the existing code lines and add curly braces `{}` to the `if`
structure for each code block.
- You could merge the two code lines that follow the final `else if` statement,
forming a single statement as follows:
```cs
} else if (name == "AllGreetings") {
msg_txt = sophia_msg() + "\n\r" + andrew_msg();
}
```
Either way, your updated code must include the call to `andrew_msg` within the
code block when `name == "AllGreetings"`.
On the **File** menu, select **Save**.
Use the debugger UI tools to clear the breakpoint that you set earlier.
On the **Run** menu, select **Start Debugging**.
Verify that your code now produces the expected results.
```txt
Hello, my name is Sophia.
Hi, my name is Andrew. Good to meet you.
Hello, my name is Sophia.
Hi, my name is Andrew. Good to meet you.
```
On the **Debug controls** toolbar, select **Stop**.
Congratulations! You've successfully used the Visual Studio Code debugger to
help you isolate and correct a logic issue.
### Recap
Here are a few important things to remember from this unit:
- Use breakpoints to pause code execution during a debug session.
- Use **Step Into** from the **Debug controls** toolbar to observe the next
executable code line.
- Use **Step Out** from the **Debug controls** toolbar to advance through the
current method and back to the code line that called the method.
---
## Examine the launch configurations file
You've already seen that Visual Studio Code uses the launch.json file to
configure the debugger. If you're creating a simple C# console application, it's
likely that Visual Studio Code generates a launch.json file that has all of the
information you need to successfully debug your code. However, there are cases
when you need to modify a launch configuration, so it's important to understand
the attributes of a launch configuration.
### Attributes of a launch configuration
The `launch.json` file includes one or more launch `configurations` in the
configurations list. The launch configurations use attributes to support
different debugging scenarios. The following attributes are mandatory for every
launch configuration:
- `name`: The reader-friendly name assigned to the launch configuration.
- `type`: The type of debugger to use for the launch configuration.
- `request`: The request type of the launch configuration.
```json
{
"version": "0.2.0",
"configurations": [
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/dotnet/vscode-csharp/blob/main/debugger-launchjson.md
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/bin/Debug/net8.0/ejm_debug.dll",
"args": [],
"cwd": "${workspaceFolder}",
// For more information about the 'console' field, see https://aka.ms/VSCode-CS-LaunchJson-Console
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}
```
This section defines some of the attributes you may encounter.
### Name
The `name` attribute specifies the display name for the launch configuration.
The value assigned to `name` appears in the launch configurations dropdown (on
the controls panel at the top of the RUN AND DEBUG view).
### Type
The `type` attribute specifies the type of debugger to use for the launch
configuration. A value of `codeclr` specifies the debugger type for .NET 5+ and
.NET Core applications (including C# applications).
### Request
The `request` attribute specifies the request type for the launch configuration.
Currently, the values `launch` and `attach` are supported.
### PreLaunchTask
The `preLaunchTask` attribute specifies a task to run before debugging your
program. The task itself can be found in the `tasks.json` file, which is in the
`.vscode` folder along with the `launch.json` file. Specifying a prelaunch task
of `build` runs a `dotnet build` command before launching the application.
### Program
The `program` attribute is set to the path of the application dll or .NET Core
host executable to launch.
This property normally takes the form:
`${workspaceFolder}/bin/Debug/<target-framework>/<project-name.dll>`.
Where:
- `<target-framework>` is the framework that the debug project is being built
for. This value is normally found in the project file as the 'TargetFramework'
property.
- `<project-name.dll>` is the name of debugged project's build output dll. This
property is normally the same as the project file name but with a '.dll'
extension.
For example: `${workspaceFolder}/bin/Debug/net7.0/Debug101.dll`
> Note
> The **.dll** extension indicates that this file is a dynamic link library
(dll) file. If your project is named Debug101, a file named **Debug101.dll** is
created when a build task compiles your program using the Program.cs and
Debug101.csproj files. You can find the **Debug101.dll** file in the EXPLORER
view by expanding the "bin" and "Debug" folders, and then opening a folder that
represents the .NET framework used by your code project, such as "net7.0". The
.NET Framework version is specified in your .csproj file.
### Cwd
The `cwd` attribute specifies the working directory of the target process.
### Args
The `args` attribute specifies the arguments that are passed to your program at
launch. There are no arguments by default.
### Console
The `console` attribute specifies the type of console that's used when the
application is launched. The options are `internalConsole`,
`integratedTerminal`, and `externalTerminal`. The default setting is
`internalConsole`. The console types are defined as:
- The `internalConsole` setting corresponds to the DEBUG CONSOLE panel in the
Panels area below the Visual Studio Code Editor.
- The `integratedTerminal` setting corresponds to the OUTPUT panel in the
Panels area below the Visual Studio Code Editor.
- The `externalTerminal` setting corresponds to an external terminal window.
The Command Prompt application that comes with Windows is an example of a
terminal window.
> Important
> The DEBUG CONSOLE panel doesn't support console input. For example, the DEBUG
CONSOLE can't be used if the application includes a `Console.ReadLine()`
statement. When you're working on a C# console application that reads user
input, the `console` setting must be set to either `integratedTerminal` or
`externalTerminal`. Console applications that write to the console, but don't
read input from the console, can use any of the three console settings.
### Stop at Entry
If you need to stop at the entry point of the target, you can optionally set
`stopAtEntry` to be `true`.
### Edit a launch configuration
There are lots of scenarios when you might need to customize the launch
configuration file. Many of those scenarios involve advanced or complex project
scenarios. This module focuses on two simple scenarios when updating the launch
configuration file is required:
- Your C# console application reads input from the console.
- Your project workspace includes more than one application.
### Update the launch configuration to accommodate console input
As you read earlier, the DEBUG CONSOLE panel doesn't support console input. If
you're debugging a console application that relies on user input, you need to
update the `console` attribute in the associated launch configuration.
To edit the `console` attribute:
Open the `launch.json` file in the Visual Studio Code Editor.
Locate the **console** attribute.
Select the colon and assigned value, and then enter a colon character.
Notice that when you overwrite the existing information with a colon, Visual
Studio Code IntelliSense displays the three options in a dropdown list.
<div align="center">
![img](./img/code_oss_debug_06.png)
</div>
Select either `integratedTerminal` or `externalTerminal`.
Save the `launch.json` file.
### Update the launch configuration to accommodate multiple applications
If your workspace has only one launchable project, the C# extension will
automatically generate the `launch.json` file. If you have more than one
launchable project, then you need to modify your `launch.json` file manually.
Visual Studio Code generates a `launch.json` file using the basic template that
you can update. In this scenario, you create separate configurations for each
application that you want to debug. Prelaunch tasks, such as a build task, can
be created in the `tasks.json` file.
Suppose that you're working on a coding project that includes several console
applications. The root project folder, **SpecialProjects**, is the workspace
folder that you open in Visual Studio Code when you work on your code. You have
two applications that you're developing, **Project123** and **Project456**.
You use the RUN AND DEBUG view to debug the applications. You want to select
the application that you're debugging from the user interface. You also want
any saved code updates to be compiled prior to attaching the debugger to your
application.
You can achieve the requirements for this scenario by updating the `launch.json`
and `tasks.json` files.
The following screenshot shows the EXPLORER view and the folder structure
containing ***Project123*** and ***Project456***.
<div align="center">
![img](./img/code_oss_debug_07.png)
</div>
Notice that the `name`, `preLaunchTask`, and `program` fields are all
configured for a specific application.
The `name` attribute specifies the selectable launch option that's displayed in
the RUN AND DEBUG view user interface, the `program` attribute specifies the
path to your application. The `preLaunchTask` attribute is used to specify the
name of the task that's performed prior to launching the debugger. The
`tasks.json` file contains the named tasks and the information required to
complete the task.
The following example shows how you could configure the tasks.json file. In
this case, the named tasks specify build operations that are specific to the
"Project123" and "Project456" applications. The build task ensures that any
saved edits are compiled and represented in the corresponding .dll file that's
attached to the debugger.
```json
"version": "2.0.0",
"tasks": [
{
"label": "buildProject123",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Project123/Project123.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
},
{
"label": "buildProject456",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/Project456/Project456.csproj",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary"
],
"problemMatcher": "$msCompile"
}
]
```
With your updates to the launch.json and tasks.json files in place, the RUN AND
DEBUG view displays launch options for debugging either the Project123 or
Project456 application. The following screenshot shows the names of the launch
configurations displayed in the launch configuration dropdown:
<div align="center">
![img](./img/code_oss_debug_08.png)
</div>
### Recap
Here are two important things to remember from this unit:
- Launch configurations are used to specify attributes such as `name`, `type`,
`request`, `preLaunchTask`, `program`, and `console`.
- Developers can edit a launch configuration to accommodate project
requirements.
---