Debugging PowerShell scripts in Visual Studio Code

When testing your new PowerShell script, it throws an expected error or isn’t that reliable and you’re not sure why πŸ™ The debugging options in Visual Studio code could help you to pinpoint the issue, in this blog post I will show you how to do that.

Example script for debugging

Below is an example script that we will use in this example, it gets a list of files from d:\temp and shows the name and creation date. It’s just an example to show how the debugger works, the script works just fine πŸ™‚

Foreach ($file in get-childitem d:\temp) {
    write-host ("File {0} found with creation date {1}" -f $file.name, $file.CreationTime)
}

Debugging

When executing the script, it runs and outputs data to your screen. But how do you know what is in the variable $file while running the script for example?

Starting run and debug for the first time

If you have never used run and debug, then it will ask you to create a launch.json file:

Click on create a launch.json file and it will ask to Select a PowerShell debug configuration:

Select Launch Current File:

Close the launch.json file and return to your script to get started.

Using run and debug

Now that you have configured the debug configuration, you can start debugging your file in different ways which are shown below.

Setting a breakpoint

If you want to see the contents of the variables being used somewhere in the script, you can place a breakpoint on that line. You do this by moving your mouse pointer just behind the line number, a red dot should appear and you can click on that:

Down in the bottom left, you should see (If you click on Breakpoints) that in the file x.ps1 (our example script) there is a breakpoint now on line 2:

If you run the script now, the line will be marked like this indicating that there is a breakpoint on that line:

Note: To remove a breakpoint, just click on it again

Variables

You should now see, in the Variables pane on the left, the first entry of the $files variable in the Script section:

Debug toolbar

While the script is being debugged, there’s also a toolbar visible on the top:

The first button is Continue (F5), this will continue the script. In this case, it will process the second item in the $file variable

The second button is Step Over (F10), this will execute the next statement. In this case, it will continue the Foreach loop

The third button is Step Into (F11), this will execute the current statement. In this case, it will run the write-host command and jump back to line 1 and execute line 2 on the next click, etc.

The fourth button is Step Out (Shift+F11), this will execute the script until the end. In this case, it will just continue the Foreach loop but if you would have put the breakpoint on line 4 and there were additional commands there… It would run all of those and stop the debugger.

The fifth button is Restart (CTRL+Shift+F5), this will restart the script. In this case, it would wait for you to click the Continue or Step Over to start the Foreach loop.

The sixth and last button is Stop (Shift+F5), this will stop the script.

Watch

You can also watch certain things in your script while debugging, click on the + button in the scripts pane:

You can add the $file for example to track that while running if you set a breakpoint on line 2 as we did in the variables section:

It will show $files: not available after adding, but if you run the script it will look like this:

It’s easier to add variables to the Watch pane and see how they are populated, but you can also add commands to the Watch pane too. In this example, I’m checking the status of the Windows Update service by adding it to the Watch pane as “(Get-Service wuauserv).Status” If you debug the script now, it shows the status in the Watch pane like this:

Call Stack

The Call Stack pane shows the progress of the script and how it was started:

In our example, it was started in an Interactive Session from Visual Studio Code and it’s in a ScriptBlock. The numbers behind ScriptBlock indicate where the Breakpoint was set, in our case on line 2 and column 5. Depending on your script, this will show multiple lines and if you click on one of them, it will take you to that part of the script.

Customizing a breakpoint

In the example above, we created a breakpoint on line two by clicking on the red circle in it. If you right-click that red circle, you get these options:

Remove Breakpoint deletes the breakpoint, similar to single-clicking the red circle again, and Disable Breakpoint leaves the breakpoint at that position so that you can enable it again when needed.

Edit Breakpoint shows a menu in which you can choose three options:

Expression will give you the option to only use the breakpoint if a certain condition is met:

For example, you could ” $filename -match ‘Intune’ ” and press Enter to save. If you now debug the script, it will show files and directories until it finds something with Intune in its name. If it does, the script stops and you can see the contents of the variable in the Variables pane (Or in the Watch pane if you were monitoring the $file variable).

Hit Count will give you the option to use the breakpoint after a certain amount of times that the script runs, in our example in the Foreach loop, past that point.

So, for our example, I could enter 10 and press Enter to save. If I debug the script again, it will output 10 files or directories and pauses the debugger.

Log Message will output a message in your console when the script is at that point, I usually use write-host at certain points to follow progress but this is nice and only in the debugger and not in the actual script.

Note: Remove the existing breakpoint first, you can configure three options simultaneously which could give undesired results πŸ˜‰

Happy debugging πŸ™‚

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.