Revisiting the PowerShell Uptime Clock

Posted on January 5, 2015 by Jeff Hicks in PowerShell with 0 Comments

We have been on a journey of PowerShell exploration. Over the last few articles, we’ve gone from a few lines of PowerShell code that you could type at the prompt to a reusable PowerShell function. Be sure to get caught up if you are joining us partway through the journey.

Remember the end result isn’t as important as what you learn along the way. The last version I showed of the Get-MyUptime command is pretty complete, but there are a few more final touches that we can apply. Let me show you the next version and then I’ll explain.

The first major change is that I inserted comment-based help. Even though it is a comment, PowerShell will process it. Here’s an outline of the commonly used sections.

At minimum I would suggest using Synopsis, Description, and one example. Be careful with your formatting and spelling, as there is a period before each entry. Some people put the heading in upper case to make it easier to read. As long as it is spelled properly, PowerShell doesn’t care. Unfortunately, if there is a typo in one of the headings or syntax error, then PowerShell won’t display an error, nor will it show your help content. The headings are the same that you see in cmdlet help. When you write the description, you don’t have to worry about line breaks. I tend to write the description in the ISE until I reach the logical end of a paragraph. It will be a long series of lines in the ISE, but when PowerShell displays the help, then it will automatically format line length for me.

Sponsored

PowerShell will detect and automatically display your parameters and syntax. Additionally, you can include a parameter part to your help. In my function, I have a parameter help definition for Computername.

You can also have as many examples as you’d like. You don’t need to number them, just add example sections. For example, I include the PS prompt in my example. It isn’t required, but if you only insert your command, the help system will generate a prompt of C:\PS>, which looks like the PS directory to me. Personally, I prefer my example prompt to look like my console: PS C:\>.

The link section is for related cmdlets. You can have as many cmdlet names as you want under a single Link heading. If you want to provide a link to online help for something, put that in a separate link. When you are finished, the person running your command can ask for help like any other command.

Related links for Windows PowerShell cmdlets. (Image Credit: Jeff Hicks)

Related links for Windows PowerShell cmdlets. (Image Credit: Jeff Hicks)

 

They can even use help’s Show-Window parameter.

Help for Get-MyUptime cmdlet. (Image Credit: Jeff Hicks)

Help for Get-MyUptime cmdlet. (Image Credit: Jeff Hicks)

 

Next, let’s look at a few other changes I made to make this even more resilient and easy to use. The heart of the function is the Get-CimInstance command. I am using Try/Catch statement to properly handle errors. One of the drawbacks with my previous version that it wasn’t always easy to tell which error message went with which computername. So instead of simply writing the error object, I like to use Write-Warning.

The first line will let me know what computer failed, and the second will display the relevant error message. I rarely need the complete exception object. But if I did, I can still find it in the global $error variable.

My other major change is to add a parameter and some logic to test the computer before I attempt to use Get-CimInstance. You can think of this process as pre-error handling. Again, the method in which I’m using it is more important than the end result. I could have used Test-Connection to ping the computer, but Get-CimInstance really needs the remote computer to be running PowerShell 3.0 or later. I can get that information using Test-WSMan.

Using Test-WSMan in Windows PowerShell. (Image Credit: Jeff Hicks)

Using Test-WSMan in Windows PowerShell. (Image Credit: Jeff Hicks)

 

I can figure out the version from the highlighted values. Because obtaining that value is a little tricky, I wrote a function to check the version. If my function determines if the version is 3.0 or later, then it writes $True to the pipeline.

I’m not using a standard naming convention because this is a function that I only intend to use within Get-MyUptime. It has to be defined before I can call it so I insert it into the begin block. This defines the function before any pipelined names are processed. Within the process block, I’ve written logic to determine if the computer has the proper version, assuming the person running the script used the –Test parameter.

It is possible that a computer could test OK for WSMan, but still fail with Get-CimInstance, which is why I still have error handling with Try/Catch. Let’s put it all to the test.

Warning in Windows PowerShell. (Image Credit: Jeff Hicks)

Warning in Windows PowerShell. (Image Credit: Jeff Hicks)

 

You can see the errors now as warnings. Or I can test.

In this example I also decided to group the results by the number of days, and I turned the uptime back into a string.

Grouping results by number of days in Windows PowerShell. (Image Credit: Jeff Hicks)

Grouping results by number of days in Windows PowerShell. (Image Credit: Jeff Hicks)

 

And remember those aliases for the Computername parameter? You may have noticed a few changes in this version. Because I decided that the person running this tool will most likely be querying Active Directory for computer names, I wanted to make it as easy as possible to connect the different cmdlets together in a single command.

Sponsored

The object from Get-ADComputer doesn’t have a Computername parameter, but it does have one called Name. All of this allows me to do this:

When I receive the job I’ll get warnings for computers that failed the test, but the grid view will have my results.

Domain Uptime. (Image Credit: Jeff Hicks)

Domain Uptime. (Image Credit: Jeff Hicks)

 

Finally, note that there are no aliases or shortcuts in my script. I am using full cmdlet and parameter names. It doesn’t really take that much longer to type, especially if you take advantage of tab completion. In any event you only have to type it once. Between the help, inline comments, Write-Verbose commands and full command names, even someone totally new to PowerShell could read through the script and have an idea of what it is doing. I strongly encourage IT pros to write scripts and tools for the next person, because you might be that next person. You might come back to a script in six months and struggle through recalling what you wrote and why. Make your life, and that of those to follow you, easier.

There is one more stop I think we can make on our journey and we’ll get there next time.

Sponsored

Tagged with , ,