Posey's Tips & Tricks
How To Debug a PowerShell Script
One of the most difficult things about PowerShell scripting is finding and fixing any bugs that exist within the script. This process isn't usually a big deal for short PowerShell scripts, but it can be tough if you are writing a long script.
That being the case, I wanted to pass along a few of the techniques I use.
Create Visual Indicators
Whenever a PowerShell script is behaving in a way that is completely unexpected, one of the first things I do is put some code in place to help me figure out what portions of the script have and have not executed. Let me give you a really simple example:
Function Do-Something {
$A = '1234'
}
Do-Something
As you can see, I have created a simple four-line PowerShell script. This script's last line calls a function called Do-Something. That function creates a variable named A and sets it equal to 1234. In case you are wondering, this script does not do anything useful; I am simply using it to illustrate a point.
Imagine that the four lines of code shown above were actually part of a much longer and more complex script. Let's also pretend that the script is not doing what it should, but is not generating any errors. One of the best ways to figure out what's going on is inserting a few lines of code that can help you trace the script. Here is an example:
Function Do-Something {
$A = '1234'
Write-Host 'The Do-Something function is executing'
}
Write-Host 'The main body is executing'
Do-Something
Write-Host 'The function has completed and the script has returned to the main body'
You can see what this looks like in Figure 1.
In this case, my script doesn't actually do anything so the only thing you are seeing in the output is the indicators that I have put into place. But imagine what this would look like in the real world. The visual indicators that you put into place would likely be displayed after various output items. That would give you a feel for which portion of the script is generating the various output items.
Variable Values
Another technique I frequently use when debugging complex PowerShell scripts is adding code to display the value of seemingly problematic variables at various points in the script. Here is another really simple example of how this technique works:
Function Do-Something {
$A = '1234'
}
$A = '5678'
Do-Something
$A
This script sets the variable $A to a value of 5678. It then calls a function that sets the variable to a value of 1234. It then displays the variable's value. If you look at Figure 2, you can see that the variable's final value at the end of the script is 5678. The reason why it isn't 1234 is because even though the function manipulates the variable, the new value isn't being passed back to the script body.
But let's pretend that we didn't know this and were expecting the value to be 1234. Here is how we might modify the script to figure out the reason for the unexpected value:
Function Do-Something
{
Write-Host 'The Do-Something function has been called'
Write-Host 'The variables current value is: ' $A
Write-Host 'The next line sets the variables value to 1234'
$A = '1234'
Write-Host 'The variables value is: ' $A
}
Write-Host 'The main body is executing'
Write-Host 'The next line of code sets the variable to 5678. The variables value prior to the assignment is: ' $A
$A = '5678'
Write-Host 'The variables value after the assignment is: ' $A
Do-Something
Write-Host 'The function has ended and the script has returned to the main body'
Write-Host 'The variables final value is: ' $A
As you can see, I added lines that cause the script to display both the portion of the script that is being executed and the value of the variable at each point within the script. This technique, while labor-intensive, can go a long way toward helping you to figure out the source of unexpected variable assignments.
Beware of Punctuation
One last thing I want to mention is that it is important to be careful about your use of punctuation within Write-Host statements.
If you look at the code above, you will notice that my text is grammatically incorrect (variables instead of variable's). The reason for this is using an apostrophe to make the text grammatically correct changes the code's syntax, causing it to malfunction. There are ways to insert an apostrophe without breaking the code in the process -- but that is another discussion for another day.
About the Author
Brien Posey is a 22-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.