The Surly Admin

Father, husband, IT Pro, cancer survivor

Comments and what you can do with them

One of the lesser documented things that Powershell can do is the special commands available in comments.  Normally a comment is just that, something to help document your script and move on.  But with Powershell we have a couple of extra things you can do too.  Read on!

Comment-Based Help

By far the coolest thing about Powershell comments is Comment-Based Help.  Using this, you can create a built-in help file that will exactly match the help files for any other cmdlet or function out there.  This provides a consistent look and feel to the help files.  Nothing more frustrating than seeing someone post a script with no comments and you literally have to read the code and try to figure out what it is the script is trying to do.  When I see those, I usually don’t even try, and just move on–but who knows?  Maybe it’s a really cool script?

Using Comment-Based Help completely solves this problem.  To get a truly detailed look into Comment-Based Help you need go no further than your Powershell prompt and type:

Help About_Comment_Based_Help

I like using Help over Get-Help because it automatically pipes it into the MORE cmdlet, which pauses after each page.  When you look at the help, you can see quite a few “.” options you can use.  I like to use these:

.SYNOPSIS
.DESCRIPTION
.PARAMETER
.EXAMPLE
.INPUTS
.OUTPUTS
.NOTES
.LINK

And it’s up to you how fancy or detailed you want to get.  For simple scripts keep it short and sweet, but for more advanced ones it makes more sense to get as detailed as you can.  I like to use INPUTS and OUTPUTS to show what files I need to read in, or what reports are being put out by the script.  If your script needs object information from the pipeline, or outputs its own object you should record that here.  If using a custom PSObject you could even go as far as showing what properties it’s putting out–like I said, you can be as detailed or not as you want.

In the NOTES section I like to put my authoring information, twitter name, Spiceworks user name and the change log.  Great way to document your script as it evolves without having to have separate help files and other tools.

In the LINK section I usually put a URL to the source code, and if I blogged about the script I’ll include the URL there.  An interesting feature of LINK is you can use Get-Help with the -Online parameter and Powershell will open your web browser and go to the online version of your help file.  I’ve always designated my LINK section like so:

.LINK
     Source:     http://someurl.com/sourcecode
     Blog:       http://www.thesurlyadmin.com/somepage

Which was great to read, but turns out doesn’t work too well with the Get-Help cmdlet and the -Online parameter.  So how do you include multiple links?  Turns out you have to use multiple LINK commands in your help.  So the above should really read:

.LINK
     http://someurl.com/sourcecode
.LINK
     http://www.thesurlyadmin.com/somepage

Now, when you use Get-Help with the -Online parameter Powershell will open your browser and navigate to the first link.  That way, if you have a script that you want to do a different style of help, or just want to provide some online help for it you can.  Next project, go through Spiceworks and fix my Comment-Based Help!

Here’s what my NOTES section looks like.  I actually try not to talk too much about the script in the NOTES section, just because I feel that should be in the full description, the logic–at least my logic–being that a person shouldn’t have to look all over the place for the information they need on the script.  Read the description and get what you need.


.NOTES
     Author:      Martin Pugh
     Twitter:     @thesurlyadm1n
     Spiceworks:  Martin9700
     Blog:        www.thesurlyadmin.com

     Changelog
         1.0      Initial release

From here I can record everything about me (a little advertising never hurt) and also begin recording major changes to the script as I move along.  Now, I’ll be the first to admit I don’t have any hard and fast way of tracking version numbers beyond what I feel is the right thing to do.  I’m no developer and the rules of versioning are something I’ve never really looked into.  But as a general rule of thumb I do minor upgrades (1.0 to 1.1) for fixes to code and major updates (1.0 to 2.0) for big re-writes or massive functionality improvements/adds.

Speaking of Versions

Another nice comment based command is #requires.  You don’t see this one a lot, but it’s really pretty useful, especially if you’re writing in Powershell 3.0.  Why?  Most people seem to still be on version 2 of Powershell, and there are even a few programs (Exchange 2010 for instance) that are still incompatible with 3.0.  with #Requires you can actually specify what version of Powershell is needed to run your script.

#Requires -Version 3

Now your script won’t even run if you don’t have Powershell 3 installed.  You can also use #Requires for snapins:

#Requires -PSSnapIn Microsoft.PowerShell.Security

Combine the -PSSnapIn parameter with the -Version parameter and you can even specify specific versions of snapins required for you script.  Which brings up an interesting point.  Should you just use #requires for your snapins or should you load them inside your script?  Certainly the former is easier, but the later is more user-friendly.  But then you not only have to load the snapin, you have to error check to make sure it loaded.  What should you do?  I’m a user experience (which now has its own industry acronym UX) fiend and will go through a lot of extra work to make sure the script runs as seamlessly as possible, so my opinion is you should do it in the script.  But maybe you just want to get the script up and running as fast as possible, and your audience is a lot of experienced Windows Administrators so you let them handle the messy stuff.

Make your code friendly

I do a lot to make my code friendly, often eschewing the pipeline so my code is more friendly to read.  Making little comments along the way to try to show what’s going on and when (though I don’t go too overboard with this because often the comments will start outweighing the code and actually having the opposite effect of what you’re trying to do).  Great blog about this over at Microsoft Scripting Guys!  Another thing you can do is use the #region command.  #Region is really meant for Integrated Scripting Environment’s (ISE) and allows you to “group” code together.  Most ISE’s will then allow you to “collapse” the grouped code.  You could put all of your functions in a region, thus tucking it away so you don’t have to look at it all the time while coding.

#region Functions
Function MyFunctions
{
   Write-Host "Hello World!"
}
#endregion

You use the #endregion to designate the end of your reason.  Very useful for larger scripts where you have a lot of things going on.

The Take Away

The big take away is, use comments!  Definitely use comment-based help!  I really am a big fan of the comment-based help and can’t encourage its use enough.  I like to watch the Powershell Repository over at Poshcode.org and it pains me to see someone posting what might be an interesting script–publicly–with very little comments.  Many times the name of the script does not give you enough information to figure out it’s purpose–for example, there’s one right now called Get-Tree.  My first guess is it provides a tree like listing of  your directory structure.  But no, it produces an ASCII based Christmas tree.  Luckily, he has some comment-based help in there and the purpose becomes clear.

My advice, if you plan on publishing a script for public consumption, on Poshcode.org, or Spiceworks or your site of choice, make sure to put complete comment-based help in there.  Assume your audience is a Powershell newbie–and we all were at some point–and write your description and examples with that in mind.  Hell, go the extra mile and write you script with that person in mind and do as much as you can to help that person out.

How do you use comments?  Would love to hear from you!

Advertisements

December 17, 2012 - Posted by | Powershell - Best Practices | , ,

3 Comments »

  1. […] did I use #Region?  Just to make the code a little neater, you can read more about it here.  I used Get-Mailbox to verify if the user exists or not, I use the Break statement to exit out of […]

    Pingback by User Termination Automation – Part 1 « The Surly Admin | December 27, 2012 | Reply

  2. […] be cranking out good documentation with every script you do.  Read more about comment-based help here.  I’ve seen scripts come out at Poshcode.org that I litterally had no idea what they did and […]

    Pingback by Powershell Best Practices – Surly Style « The Surly Admin | December 31, 2012 | Reply

  3. […] And just to pretty it up as a Function and with comment-based help: […]

    Pingback by Quick Script: Date Ranges « The Surly Admin | July 25, 2014 | Reply


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: