diff --git a/033_Debug_console_apps_2/033_csharp.md b/033_Debug_console_apps_2/033_csharp.md
index 9b5e476..ddc3e68 100644
--- a/033_Debug_console_apps_2/033_csharp.md
+++ b/033_Debug_console_apps_2/033_csharp.md
@@ -1067,3 +1067,508 @@ Here are two important things to remember from this unit:
requirements.
---
+
+## Configure conditional breakpoints in C#
+
+The C# debugger for Visual Studio Code supports the option to configure a
+breakpoint that only triggers if a condition is met. This type of breakpoint is
+called a conditional breakpoint. Conditional breakpoints can be configured
+directly or by editing an existing breakpoint.
+
+> Note
+> Visual Studio Code also supports a conditional breakpoint that triggers based
+on the number of times the breakpoint has been "hit".
+
+Suppose you're debugging an application that processes product information in a
+multidimensional string array. The array includes thousands of data points. The
+problem that you're debugging seems to occur for products that are marked as
+new. Your code processes the array inside a `for` loop. You need to set a
+breakpoint inside the loop, but you only want to pause when products are `new`.
+
+### Use a standard breakpoint to examine a data processing application
+
+Replace the contents of your Program.cs file with the following code:
+
+```cs
+int productCount = 2000;
+string[,] products = new string[productCount, 2];
+
+LoadProducts(products, productCount);
+
+for (int i = 0; i < productCount; i++) {
+ string result;
+ result = Process1(products, i);
+ if (result != "obsolete") {
+ result = Process2(products, i);
+ }
+}
+
+bool pauseCode = true;
+while (pauseCode == true) ;
+```
+
+This code uses a method named `LoadProducts` to load data into the `products`
+array. After the data is loaded, the code iterates through the array and calls
+methods named `Process1` and `Process2`.
+
+To generate data for the simulated processes, add the following method to the
+end of your Program.cs file:
+
+```cs
+static void LoadProducts(string[,] products, int productCount) {
+ Random rand = new Random();
+ for (int i = 0; i < productCount; i++) {
+ int num1 = rand.Next(1, 10000) + 10000;
+ int num2 = rand.Next(1, 101);
+ string prodID = num1.ToString();
+ if (num2 < 91) {
+ products[i, 1] = "existing";
+ } else if (num2 == 91) {
+ products[i, 1] = "new";
+ prodID = prodID + "-n";
+ } else {
+ products[i, 1] = "obsolete";
+ prodID = prodID + "-0";
+ }
+ products[i, 0] = prodID;
+ }
+}
+```
+
+The `LoadProducts` method generates 2000 random product IDs and assigns a value
+of `existing`, `new`, or `obsolete` to a product description field. There is
+about a 1% chance that the products are marked `new`.
+
+To simulate data processing, add the following methods to the end of your
+Program.cs file:
+
+```cs
+static string Process1(string[,] products, int item) {
+ Console.WriteLine(
+ $"Process1 message - working on {products[item, 1]} product"
+ );
+ return products[item, 1];
+}
+
+static string Process2(string[,] products, int item) {
+ Console.WriteLine(
+ $"Process2 message - working on product ID #: {products[item, 0]}"
+ );
+ if (products[item, 1] == "new") {
+ Process3(products, item);
+ }
+ return "continue";
+}
+
+static void Process3(string[,] products, int item) {
+ Console.WriteLine(
+ $"Process3 message - processing product information for 'new' product"
+ );
+}
+```
+
+The `Process1` and `Process2` methods display progress messages and return a
+string.
+
+Notice that the `Process2` method calls `Process3` if the product is `new`.
+
+On the Visual Studio Code File menu, select Save.
+
+Near the top of the Program.cs file, set a breakpoint on the following code
+line:
+
+ ```cs
+ result = Process1(products, i);
+ ```
+
+Open the RUN AND DEBUG view, and then select **Start Debugging**.
+
+
+
+ ![img](./img/code_oss_debug_09.png)
+
+
+
+Use Step Into to walk through the code for `Process1` and `Process2`.
+
+Notice the updates to the VARIABLES and CALL STACK sections of the RUN AND
+DEBUG view.
+
+Continue to use Step Into to walk through the code until you see that `i` is
+equal to 3.
+
+The VARIABLES section of the RUN AND DEBUG view displays the value assigned to
+`i`.
+
+
+
+ ![img](./img/code_oss_debug_10.png)
+
+
+
+Notice that `Process1` and `Process2` display messages to the DEBUG CONSOLE
+panel. A real application may require user interactions as data is being
+processed. Some interactions may be dependent on the data being processed.
+
+Use the **Stop** button to stop code execution.
+
+### Configure a conditional breakpoint using an expression
+
+A standard breakpoint is great for walking through a data processing
+application. However, in this case you're interested in `new` products and you
+don't want to walk through the analysis of each product to find the ones that
+are `new`. This scenario is a good example of when conditional breakpoints
+should be used.
+
+Right-click your existing breakpoint, and then select `Edit Breakpoint`.
+
+Enter the following expression:
+
+ ```cs
+ products[i,1] == "new";
+ ```
+
+
+
+ ![img](./img/code_oss_debug_11.png)
+
+
+
+Notice that the expression is no longer displayed after you press Enter.
+
+To display the expression temporarily, hover the mouse pointer over the
+breakpoint (red dot).
+
+
+
+ ![img](./img/code_oss_debug_12.png)
+
+
+
+To run your application with the conditional breakpoint configured, select
+**Start Debugging**.
+
+Wait for the application to pause at the conditional breakpoint.
+
+Notice the value of `i` displayed under the VARIABLES section.
+
+On the **Debug controls** toolbar, select **Continue**
+
+Notice that the value of `i` has been updated the VARIABLES section.
+
+
+
+ ![img](./img/code_oss_debug_13.png)
+
+
+
+Select **Step Into**.
+
+Continue selecting **Step Into** until the `Process1` message is displayed.
+
+Notice that `Process1` reports that it's working on a **new** product.
+
+
+
+ ![img](./img/code_oss_debug_14.png)
+
+
+
+Take a moment to consider the advantage that conditional breakpoints offer.
+
+In this simulated data processing scenario, there is about a 1% chance that a
+product is `new`. If you're using a standard breakpoint to debug the issue,
+you'd need to walk through the analysis of about 100 products to find one of
+the `new` products that you're interested in.
+
+Conditional breakpoints can save you lots of time when you're debugging an
+application.
+
+Use the **Stop** button to stop code execution.
+
+Congratulations! You successfully configured a conditional breakpoint.
+
+### Recap
+
+Here are two important things to remember from this unit:
+
+- Use a standard breakpoint to pause an application each time a breakpoint is
+encountered.
+- Use a conditional breakpoint to pause an application when a Boolean
+expression evaluates to `true`.
+
+---
+
+## Exercise - Monitor variables and execution flow
+
+The RUN AND DEBUG view provides developers with an easy way to monitor
+variables and expressions, observe execution flow, and manage breakpoints
+during the debug process.
+
+Examine the sections of the Run and Debug view
+Each section of the RUN AND DEBUG view provides unique capabilities. Using a combination of these sections during the debug process is often helpful.
+
+### VARIABLES section
+
+Monitoring variable state is an important aspect of code debugging. Unexpected
+changes in variable state will often help to identify logic errors in your code.
+
+The VARIABLES section organizes your variables by scope. The `Locals` scope
+displays the variables in the current scope (the current method).
+
+> Note
+> The top-level statements section of a console application is considered its
+own method. A method named `Main`.
+
+You can unfold (expand) the displayed scopes by selecting the arrow to the left
+of the scope name. You can also unfold variables and objects. The following
+screenshot shows the `numbers` array unfolded under the `Locals` scope.
+
+It's also possible to change the value of a variable at runtime using the
+VARIABLES section. You can double-click the variable name and then enter a new
+value.
+
+### WATCH section
+
+What if you want to track a variable state across time or different methods? It
+can be tedious to search for the variable every time. That's where the WATCH
+section comes in handy.
+
+You can select the **Add Expression** button (appears as a plus sign: +) to
+enter a variable name or an expression to watch. As an alternative, you can
+right-click a variable in the VARIABLES section and select `Add to watch`.
+
+All expressions inside the WATCH section will be updated automatically as your
+code runs.
+
+### CALL STACK section
+
+Every time your code enters a method from another method, a call layer is added
+to the application's call stack. When your application becomes complex and you
+have a long list of methods called by other methods, the call stack represents
+the trail of method calls.
+
+The CALL STACK section is useful when you're trying to find the source location
+for an exception or WATCH expression. If your application throws an unexpected
+exception, you'll often see a message in the console that resembles the
+following:
+
+```txt
+Exception has occurred: CLR/System.DivideByZeroException
+An unhandled exception of type 'System.DivideByZeroException' occurred in Debug1.dll: 'Attempted to divide by zero.'
+ at Program.<$>g__WriteMessage|0_1() in C:\Users\howdc\Desktop\Debug1\Program.cs:line 27
+ at Program.<$>g__Process1|0_0() in C:\Users\howdc\Desktop\Debug1\Program.cs:line 16
+ at Program.$(String[] args) in C:\Users\howdc\Desktop\Debug1\Program.cs:line 10
+```
+
+The indented group of `at Program ...` lines under the error message is called
+a stack trace. The stack trace lists the name and origin of every method that
+was called leading up to the exception. The information can be a bit difficult
+to decipher though, because it can also include information from the .NET
+runtime. In this example, the stack trace is pretty clean and you can see that
+exception occurred in a method named `WriteMessage`. The stack originates in a
+method named `Main`, which is the top-level statements section of the console
+application.
+
+The CALL STACK section can help you to avoid the difficulty of deciphering a
+stack trace that's cluttered with .NET runtime information. It filters out
+unwanted information to show you only the relevant methods from your own code
+by default. You can manually unwind the call stack to find out where the
+exception originated.
+
+### BREAKPOINTS section
+
+The BREAKPOINTS section displays the current breakpoint settings and can be
+used to enable or disable specific breakpoints during a debug session.
+
+### Configure your application and launch configuration
+
+When you're working on a console application that reads user input, you'll
+probably need to update launch configuration file.
+
+Update the code in your Program.cs file as follows:
+
+```cs
+string? readResult;
+int startIndex = 0;
+bool goodEntry = false;
+
+int[] numbers = { 1, 2, 3, 4, 5 };
+
+// Display the array to the console.
+Console.Clear();
+Console.Write("\n\rThe 'numbers' array contains: { ");
+foreach (int number in numbers) {
+ Console.Write($"{number} ");
+}
+
+// To calculate a sum of array elements,
+// prompt the user for the starting element number.
+Console.WriteLine($"}}\n\r\n\rTo sum values 'n' through 5, enter a value for 'n':");
+while (goodEntry == false) {
+ readResult = Console.ReadLine();
+ goodEntry = int.TryParse(readResult, out startIndex);
+ if (startIndex > 5) {
+ goodEntry = false;
+ Console.WriteLine("\n\rEnter an integer value between 1 and 5");
+ }
+}
+
+// Display the sum and then pause.
+Console.WriteLine(
+ $"\n\rThe sum of numbers {startIndex} through " +
+ $"{numbers.Length} is: {SumValues(numbers, startIndex)}"
+);
+Console.WriteLine("press Enter to exit");
+readResult = Console.ReadLine();
+
+// This method returns the sum of elements n through 5
+static int SumValues(int[] numbers, int n) {
+ int sum = 0;
+ for (int i = n; i < numbers.Length; i++) {
+ sum += numbers[i];
+ }
+ return sum;
+}
+```
+
+Take a minute to review the code.
+
+Notice the following:
+
+- The code specifies an integer array containing five numbers.
+- The code displays output in the console.
+- The code prompts the user to enter a starting element number `n` that it uses
+to sum array elements `n` through `5`.
+- The code calculates the sum in a method, displays the results in the console,
+and then pauses.
+
+> Note
+> The DEBUG CONSOLE panel does not support user input from the console.
+
+On the Visual Studio Code **File** menu, select **Save**.
+
+On the Run menu, select Remove All Breakpoints.
+
+This removes any breakpoints left over from the previous exercise.
+
+On the RUN AND DEBUG view, select Start Debugging.
+
+Notice that an error occurs when the `Console.Clear();` code line is executed.
+
+On the **Debug toolbar**, select **Stop**.
+
+Switch to the EXPLORER view, and then open the launch.json file in the Editor.
+
+Update the value of the `console` attribute as follows:
+
+```json
+"console":"integratedTerminal",
+```
+
+On the Visual Studio Code **File** menu, select **Save**, and then close the
+launch.json file.
+
+### Review application output and identify issues
+
+Reviewing the output of your application can reveal logic issues that you've
+overlooked when writing your code.
+
+Switch back to the RUN AND DEBUG view.
+
+On the RUN AND DEBUG view, select **Start Debugging**.
+
+The messages displayed to the DEBUG CONSOLE panel show the debugger attaching
+to the `Debug101.dll` application.
+
+Notice that no error messages are displayed.
+
+Changing the value of the `console` attribute from **internalConsole** to
+**integratedTerminal** in the launch configuration file has fixed the console error. But now you need to locate the console that contains your output.
+
+In the Panels area below the Editor, switch from the DEBUG CONSOLE panel to the
+TERMINAL panel.
+
+Notice that code execution has paused at the message prompting the user to
+enter a value for `n`.
+
+The output on the TERMINAL panel should look like the following:
+
+ ```txt
+ The 'numbers' array contains: { 1 2 3 4 5 }
+
+ To sum values 'n' through 5, enter a value for 'n':
+ ```
+
+At the TERMINAL command prompt, enter **3**
+
+Review the output from the application.
+
+The output on the TERMINAL panel should look like the following:
+
+ ```txt
+ The 'numbers' array contains: { 1 2 3 4 5 }
+
+ To sum values 'n' through 5, enter a value for 'n':
+ 3
+
+ The sum of numbers 3 through 5 is: 9
+ press Enter to exit
+ ```
+
+Take a minute to consider the reported value of `sum` and the values of array
+elements 3 through 5 displayed at the top of the console.
+
+The message says: `The sum of numbers 3 through 5 is: 9`. However, array
+elements 3 through 5 are `3`, `4`, and `5`. Shouldn't the reported sum be 12?
+
+You can use the VARIABLES section of the RUN AND DEBUG view to investigate the
+issue.
+
+### Monitor variable state
+
+In some cases, simply monitoring variable state is enough to identify the logic
+issue in your application.
+
+Set a breakpoint on the following code line:
+
+```cs
+Console.WriteLine($"\n\rThe sum of numbers {startIndex} through {numbers.Length} is: {SumValues(numbers, startIndex)}");
+```
+
+On the RUN AND DEBUG view, select Start **Debugging**.
+
+Switch from the DEBUG CONSOLE panel to the TERMINAL panel.
+
+At the TERMINAL command prompt, enter **3**
+
+Code execution will pause at the breakpoint.
+
+Take a minute to review the VARIABLES section of the RUN AND DEBUG view.
+
+Notice that `startIndex` has been assigned the value that you entered, which is
+`3`.
+
+Select **Step Into**.
+
+Notice that the VARIABLES and CALL STACK sections are updated.
+
+The CALL STACK section shows that code execution has moved into the `SumValues`
+method.
+
+The VARIABLES section, which lists the local variables, shows the value of the
+integer `n`. The method parameter `n` is assigned its value from the method
+call argument `startIndex`. In this case, the change to variable names makes it
+clear the value has been passed, not a reference pointer.
+
+> Note
+> In this case, you can see most of your code in the Editor, so you might not
+need the CALL STACK section, but when you're working on larger applications
+with deeply nested and interconnected method calls, the execution path shown in
+the CALL STACK section can be extremely useful.
+
+Continue selecting Step Into until the value assigned to `sum` is no longer `0`.
+
+Take a minute to review the information shown in the VARIABLES section.
+
+You should see the following:
diff --git a/033_Debug_console_apps_2/Debug101/Debug101.csproj b/033_Debug_console_apps_2/Debug101/Debug101.csproj
new file mode 100644
index 0000000..2150e37
--- /dev/null
+++ b/033_Debug_console_apps_2/Debug101/Debug101.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
diff --git a/033_Debug_console_apps_2/Debug101/Program.cs b/033_Debug_console_apps_2/Debug101/Program.cs
new file mode 100644
index 0000000..69053d5
--- /dev/null
+++ b/033_Debug_console_apps_2/Debug101/Program.cs
@@ -0,0 +1,41 @@
+string? readResult;
+int startIndex = 0;
+bool goodEntry = false;
+
+int[] numbers = { 1, 2, 3, 4, 5 };
+
+// Display the array to the console.
+Console.Clear();
+Console.Write("\n\rThe 'numbers' array contains: { ");
+foreach (int number in numbers) {
+ Console.Write($"{number} ");
+}
+
+// To calculate a sum of array elements,
+// prompt the user for the starting element number.
+Console.WriteLine($"}}\n\r\n\rTo sum values 'n' through 5, enter a value for 'n':");
+while (goodEntry == false) {
+ readResult = Console.ReadLine();
+ goodEntry = int.TryParse(readResult, out startIndex);
+ if (startIndex > 5) {
+ goodEntry = false;
+ Console.WriteLine("\n\rEnter an integer value between 1 and 5");
+ }
+}
+
+// Display the sum and then pause.
+Console.WriteLine(
+ $"\n\rThe sum of numbers {startIndex} through " +
+ $"{numbers.Length} is: {SumValues(numbers, startIndex)}"
+);
+Console.WriteLine("press Enter to exit");
+readResult = Console.ReadLine();
+
+// This method returns the sum of elements n through 5
+static int SumValues(int[] numbers, int n) {
+ int sum = 0;
+ for (int i = n; i < numbers.Length; i++) {
+ sum += numbers[i];
+ }
+ return sum;
+}
diff --git a/033_Debug_console_apps_2/conditional_brakpoints/Program.cs b/033_Debug_console_apps_2/conditional_brakpoints/Program.cs
new file mode 100644
index 0000000..e14cef5
--- /dev/null
+++ b/033_Debug_console_apps_2/conditional_brakpoints/Program.cs
@@ -0,0 +1,57 @@
+int productCount = 2000;
+string[,] products = new string[productCount, 2];
+
+LoadProducts(products, productCount);
+
+for (int i = 0; i < productCount; i++) {
+ string result;
+ result = Process1(products, i);
+ if (result != "obsolete") {
+ result = Process2(products, i);
+ }
+}
+
+bool pauseCode = true;
+while (pauseCode == true) ;
+
+static void LoadProducts(string[,] products, int productCount) {
+ Random rand = new Random();
+ for (int i = 0; i < productCount; i++) {
+ int num1 = rand.Next(1, 10000) + 10000;
+ int num2 = rand.Next(1, 101);
+ string prodID = num1.ToString();
+ if (num2 < 91) {
+ products[i, 1] = "existing";
+ } else if (num2 == 91) {
+ products[i, 1] = "new";
+ prodID = prodID + "-n";
+ } else {
+ products[i, 1] = "obsolete";
+ prodID = prodID + "-0";
+ }
+ products[i, 0] = prodID;
+ }
+}
+
+static string Process1(string[,] products, int item) {
+ Console.WriteLine(
+ $"Process1 message - working on {products[item, 1]} product"
+ );
+ return products[item, 1];
+}
+
+static string Process2(string[,] products, int item) {
+ Console.WriteLine(
+ $"Process2 message - working on product ID #: {products[item, 0]}"
+ );
+ if (products[item, 1] == "new") {
+ Process3(products, item);
+ }
+ return "continue";
+}
+
+static void Process3(string[,] products, int item) {
+ Console.WriteLine(
+ $"Process3 message - processing product information for 'new' product"
+ );
+}
diff --git a/033_Debug_console_apps_2/conditional_brakpoints/conditional_brakpoints.csproj b/033_Debug_console_apps_2/conditional_brakpoints/conditional_brakpoints.csproj
new file mode 100644
index 0000000..2150e37
--- /dev/null
+++ b/033_Debug_console_apps_2/conditional_brakpoints/conditional_brakpoints.csproj
@@ -0,0 +1,10 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
diff --git a/033_Debug_console_apps_2/img/code_oss_debug_09.png b/033_Debug_console_apps_2/img/code_oss_debug_09.png
new file mode 100644
index 0000000..5264bf3
Binary files /dev/null and b/033_Debug_console_apps_2/img/code_oss_debug_09.png differ
diff --git a/033_Debug_console_apps_2/img/code_oss_debug_10.png b/033_Debug_console_apps_2/img/code_oss_debug_10.png
new file mode 100644
index 0000000..ecfe9d2
Binary files /dev/null and b/033_Debug_console_apps_2/img/code_oss_debug_10.png differ
diff --git a/033_Debug_console_apps_2/img/code_oss_debug_11.png b/033_Debug_console_apps_2/img/code_oss_debug_11.png
new file mode 100644
index 0000000..7fb6427
Binary files /dev/null and b/033_Debug_console_apps_2/img/code_oss_debug_11.png differ
diff --git a/033_Debug_console_apps_2/img/code_oss_debug_12.png b/033_Debug_console_apps_2/img/code_oss_debug_12.png
new file mode 100644
index 0000000..62542fb
Binary files /dev/null and b/033_Debug_console_apps_2/img/code_oss_debug_12.png differ
diff --git a/033_Debug_console_apps_2/img/code_oss_debug_13.png b/033_Debug_console_apps_2/img/code_oss_debug_13.png
new file mode 100644
index 0000000..6c68d8f
Binary files /dev/null and b/033_Debug_console_apps_2/img/code_oss_debug_13.png differ
diff --git a/033_Debug_console_apps_2/img/code_oss_debug_14.png b/033_Debug_console_apps_2/img/code_oss_debug_14.png
new file mode 100644
index 0000000..ad33539
Binary files /dev/null and b/033_Debug_console_apps_2/img/code_oss_debug_14.png differ
diff --git a/README.md b/README.md
index 8483916..f3e9aeb 100644
--- a/README.md
+++ b/README.md
@@ -37,4 +37,4 @@ Following
30. [Guided project - Plan a Petting Zoo](./030_project_petting_zoo/030_csharp.md)
31. [Challenge project - Create a mini-game](./031_Challenge_mini_game/031_csharp.md)
32. [Debug console applications 1](./032_Debug_console_apps/032_csharp.md)
-32. [Debug console applications 2](./032_Debug_console_apps_2/033_csharp.md)
+32. [Debug console applications 2](./033_Debug_console_apps_2/033_csharp.md)