Skip to main content

Windows PowerShell

WTFM: Writing the Fabulous Manual

Don Jones

“RTFM” is one of the favorite acronyms of the IT industry (at least the English-speaking part of it). It’s spelled out differently by different people, but it’s generally accepted to be something like “Read the Fabulous Manual,” and it’s usually given in response to a question that probably could have been answered more quickly and completely if the asker had simply read the instructions. As you work with Windows PowerShell, however, and start creating scripts and functions for others to use, are you making sure there’s actually a set of instructions for them to read? Are you, in other words, Writing the Fabulous Manual (WTFM)?

‘No Comment’ Is Never the Right Answer

If you have any experience whatsoever with computer programming or scripting, you’re familiar with the use of in-line code comments to help document the function of a particular piece of code. Windows PowerShell naturally provides support for comments: The shell ignores any line beginning with #, allowing you to place whatever comments you like.

Unfortunately, to read these comments, you have to open the script in Windows Notepad or another editor, and that’s a different behavior from what you’d probably use for a shell cmdlet, which integrates with the shell’s built-in help system. One of the foundation concepts in Windows PowerShell is that you should only need to learn a single set of skills and behaviors for any given task; if you’ve already learned to use the Get-Help command to obtain instructions for a native cmdlet, why should things work any differently for a script or function?

In v2 of the shell, things don’t have to work differently. Windows PowerShell v2 introduces a new form of documentation called comment-based help. Essentially, the shell knows to look for specially formatted comments inside of a script or function, and it parses those comments to construct the same type of help display you’d see with a native cmdlet. Cmdlet help is actually written in an XML format; comment-based help is not only easier to construct manually, but it also travels along with whatever script or function it’s attached to, making your script or function self-contained and easier to distribute.

Let’s set a goal of producing a script or function that can display its help through the built-in Get-Help command, formatting that help exactly like that of a native cmdlet, as shown in Figure 1.

 

Figure 1 Help formatted as a native cmdlet in Windows PowerShell.

To WTFM, RTFM

Windows PowerShell includes complete built-in help for comment-based help: Just run help about_comment_based_help. Basically, the rules for comment-based help are simple:

  • The comments must be the first thing inside the script (if the help applies to the entire script) or function (if the help is specific to a function).
  • The comments must use specific formatting and keywords so that the shell’s help functionality can parse them correctly.

You can use either one-line comments, preceding each line with #, or you can use the new block comments. These are easier to type, because you don’t have to stick a # at the front of each line. Start a block comment by typing <# on a line by itself, and end it with #> on a line by itself. Anything between those two lines will be considered part of the comment.

Your help instructions will be constructed as a series of blocks. Each block begins with a section keyword, such as .SYNOPSIS or .DESCRIPTION. The actual keyword is preceded by a period, and the period must be the first character on the line, excepting spaces or the # character. The about_comment_based_help file lists all the possible keywords, but the main ones are:

  • .SYNOPSIS –a brief explanation of what the script or function does.
  • .DESCRIPTION – a more detailed explanation of what the script or function does.
  • .PARAMETER name – an explanation of a specific parameter. Replace name with the parameter name. You can have one of these sections for each parameter the script or function uses.
  • .EXAMPLE – an example of how to use the script or function. You can have multiple .EXAMPLE sections if you want to provide more than one example.
  • .NOTES – any miscellaneous notes on using the script or function.
  • .LINK – a cross-reference to another help topic; you can have more than one of these. If you include a URL beginning with http:// or https://, the shell will open that URL when the Help command’s –online parameter is used.

Each keyword goes on a line by itself and is followed by one or more lines of text. Here’s an example:

<#

.SYNOPSIS

Retrieves service pack and operating system information from one or more remote computers.



.DESCRIPTION

The Get-Inventory function uses Windows Management Instrumentation (WMI) toretrieve service pack version, operating system build number, and BIOS serial number from one or more remote computers. 

Computer names or IP addresses are expected as pipeline input, or may bepassed to the –computerName parameter. 

Each computer is contacted sequentially, not in parallel.



.PARAMETER computerNameAccepts 

a single computer name or an array of computer names. You mayalso provide IP addresses.



.PARAMETER path

The path and file name of a text file. Any computers that cannot be reached will be logged to this file. 

This is an optional parameter; if it is notincluded, no log file will be generated.



.EXAMPLE

Read computer names from Active Directory and retrieve their inventory information.

Get-ADComputer –filter * | Select{Name="computerName";Expression={$_.Name}} | Get-Inventory.



.EXAMPLE 

Read computer names from a file (one name per line) and retrieve their inventory information

Get-Content c:\names.txt | Get-Inventory.



.NOTES

You need to run this function as a member of the Domain Admins group; doing so is the only way to ensure you have permission to query WMI from the remote computers.

#>

Figure 2 shows what this might look like inside an actual function.

 

Figure 2 Helpinstructions within a function.

The Help command continues to follow its normal rules for which pieces of the help to display. For example, you’ll see only the .EXAMPLE section if you use the –example parameter, while you’ll see all of the sections if you use the –full parameter.  In any case, you’ll see (as in Figure 3) that this function’s help looks identical to a native cmdlet’s.

 

Figure 3 A function’s help that looks like a native cmdlet.

Best Practices for Comment-Based Help

I like to include at least a .SYNOPSIS and .DESCRIPTION section inside every script or function I write. If the script or function uses one or more parameters, I document those with a .PARAMETER section. That way, anybody who comes along later and needs to use the script or function can easily figure out what it does. Heck, for that matter, six months later I’ll probably have forgotten what I wrote, and I’ll need a quick refresher—which the comment-based help handily provides.

The more structured and reusable your code, the more detailed your help should be. For example, I structured my Get-Inventory example function as an “advanced function,” meaning it looks and works pretty much like a native cmdlet. That’s the highest form of life in the shell’s world, so I should provide the same level of detailed help as a “real” cmdlet—including documenting examples, notes, cross-references, inputs and outputs, and so on.

More and more third-party utilities are starting to rely on the help. For example, third-party integrated scripting environments often parse the help to provide IntelliSense-like code-hinting and -completion features within their editing environments; by including properly formatted and complete comment-based help, you’re enabling your scripts and functions to be used more easily from within those third-party tools.

Plus, it just looks cool to have scripts and functions that look as much like “real” cmdlets as possible—including the slick-looking help output.

Related Content