Add Excellent Comments to Your PowerShell Script

ScriptingGuy1

Summary: Microsoft Scripting Guy, Ed Wilson, shows you how to add excellent comments to your Windows PowerShell script.

Microsoft Scripting Guy, Ed Wilson, is here. Today is a celebration! No, it is not international Scripting Guy Day (that is January 11), rather today is our 1750th Hey Scripting Guy! blog. If it seems like only a few months ago that we celebrated our 1500th Hey Scripting Guy! blog (it was September 8, 2010), it is because these milestones are occurring much faster now that I switched to publishing seven days a week and 365 days a year.

Anyway, that is enough preliminaries. I want to talk about something I noticed during the 2011 Scripting Games. One of the hallmarks of good script design is providing useful comments. I have written about using multi-line comments in the past, but I do not think I have written about exactly what one should add in the comments.

Rather than pick on anyone’s script, partly because many scripts in both the advanced and in the beginner categories violated this guideline, I decided to write a script with lots of bogus comments. The ScriptWithLotsOfBogusComments.ps1 appears here.

ScriptWithLotsOfBogusComments.ps1

# First connect to WMI and get information about the bios

# Store the returned bios information into the $b variable

$b = Get-wmiobject win32_bios

# now I need to print out the version

# I get the version by accessing the version property

# from the object stored in the $b variable

$b.version

# I now need to see if the version number is greater than

# 14. To do this, the first thing I do is split the version

# at the dash and store that in a variable called $c

# that will give me an array of two elements. The first

# element contains the word dell and the second the number

# of the version

$c = $b.Version -split “-“

# once i have the array, i want to ensure the version number

# number has no extra spaces in it so i use trim. Trim is a

# method so i have to use () after the call. Because I am

# working with an array and I want the second element, i use

# [] to index into the array. I can also trim at the same time

# I store the resulting value into the $d variable.

$d = $c[1].trim()

# Now I check the version of the bios. First I ensure I have

# an integer by using [int] and then i use the greater than

# operator which is -gt. The action clause of an if statement

# is placed in a script block which consists of two curly

# brackets.

if([int]$d -gt 14) { “The bios is the latest version” }

I know the previous code is a bit difficult to read, but look at it in the Windows PowerShell ISE, as shown in the following image, and you can tell that it is not much better.

Image of command output

During the 2011 Scripting Games, I saw many scripts that were similar to the script above…or worse. If you read all the comments, you will see that they are not bad comments, but they do not tell anything about the script itself. In addition, there is nothing to tell us about the logic that is used—what does it mean when the script states the BIOS is the latest version? How is version 15 determined to be the latest version? What happens when the script runs on a computer that is not a Dell? There is no check for the computer version, nor is there any message other than the one that states the BIOS is the latest version if the version is greater than 15.

So, although the script has massive comments, the comments are basically useless. This makes the script useless as well. As an ITPro, I do not have enough information about the script to be able to use it to ensure that my computers have the correct BIOS installed. This points to several of my best practices regarding comments.

Best practices for comments

1. When commenting a script, do not explain things that anyone who has a moderate knowledge of Windows PowerShell scripting would already know. I know that the Get-WmiObject cmdlet connects to WMI on the target computer, and I know that the Win32_Bios WMI class returns information about the BIOS on a computer. In addition, anyone who has used Windows PowerShell for more than 15 minutes knows what a straightforward value assignment to a variable looks like. Therefore, the comment lines in the following code are useless.

# First connect to WMI and get information about the bios

# Store the returned bios information into the $b variable

$b = Get-wmiobject win32_bios

2. A good comment should explain the logic of the script. If data is returned in a particular format, and it needs grooming prior to use, it is a good practice to explain that logic in a comment. This enables the user of the script to make changes should the format of the data change in the future. In particular, this type of comment will simplify troubleshooting in the future. Unfortunately, in the following code, the comment does not really address the point of why the code is written as it is.

# I now need to see if the version number is greater than

# 14. To do this, the first thing I do is split the version

# at the dash and store that in a variable called $c

# that will give me an array of two elements. The first

# element contains the word dell and the second the number

# of the version

$c = $b.Version -split “-“

# once i have the array, i want to ensure the version number

# number has no extra spaces in it so i use trim. Trim is a

# method so i have to use () after the call. Because I am

# working with an array and I want the second element, i use

# [] to index into the array. I can also trim at the same time

# I store the resulting value into the $d variable.

$d = $c[1].trim()

3. If the script has any type of unique logic or “business rules” in it, these should be explained. In the code that follows the script checks to see if the BIOS version number is greater than 14. If it is, the script displays a message that says, “The BIOS is the latest version.” Unfortunately, the comment does not explain how the number 14 as a baseline value is obtained. Nor does it explain the limitations of the assessment, or the applicability of the results. In fact, the comment for this portion of the code simply states the obvious. In fact, it is worse than that, because it does not explain what the number 14 is doing in the code. I simply assume that the number 14 is a baseline BIOS, but that is not really explained in the comments.

# Now I check the version of the bios. First I ensure I have

# an integer by using [int] and then i use the greater than

# operator which is -gt. The action clause of an if statement

# is placed in a script block which consists of two curly

# brackets.

if([int]$d -gt 14) { “The bios is the latest version” }

So, the script has lots of comments, but those comments ignore the things that should have been commented. In addition, there are so many comments, that they obscure the actual code and make it difficult to read the script.

In the ScriptWithBetterComments.ps1 script that follows, I still have a lot of comments. But I have comments about future work items, and I explain the logic and business rules used in the script. This script is shown here.

ScriptWithBetterComments.ps1

# This script only runs on Dell computers

# TODO add computer maker check to script

# TODO add remote capability

 

$b = Get-wmiobject win32_bios

$b.version

 

# The version appears as Dell – 14. I match only

# the number, so I split the number from the string.

# In future, this code might need revision if format changes.

 

$c = $b.Version -split “-“

$d = $c[1].trim()

 

# Dell’s website states the latest bios version for our

# computers is 14, so this is what we check here.

# TODO remove string literal and use variable.

# TODO produce output when not the latest version.

 

if([int]$d -gt 14) { “The bios is the latest version” }

 

# TODO add ability to update bios if not on latest version

In addition to writing better comments, I also placed spaces between the blocks of comments. This makes the code easier to read, as shown in the following image.

Image of command output

That is a quick overview about using comments. 2011 Scripting Games Wrap-up Week will continue tomorrow.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy