2013 PowerShell Scripting Games Advanced Event 3 – Bringing Bad Habits from the GUI to PowerShell

I’m seeing a trend with a lot of PowerShell scripters. Many of us have a GUI, non-scripting background and we moved to PowerShell because we didn’t want to be button monkeys clicking through the same options in the GUI day in and day out. I’ve always heard, if you’re going to do something more than once, do it (script it) in PowerShell.

The trend I’m seeing is many are bringing their bad habit of wanting to repeat themselves over and over, day in and day out, to PowerShell. They write the same code over and over. I need a new tool to accomplish a task today. I’ll rewrite the same code that I’ve written every time I’ve had to accomplish a similar task again today so there will be fifty thousand copies of similar code out there, each in a different function to accomplish a similar task. No, no, no! Now you’re thinking like a script monkey instead of a button monkey, the only difference is you’re repeating yourself in PowerShell instead of the GUI.

A new day and a new way. Write reusable code, write it once and be done with it! That way when a modification needs to be made, it only needs to be made once or at least a lot less. Redundant data is a bad thing. What? I thought redundant data was what we wanted in IT? No (period). Redundancy of systems to prevent failure and to keep them online in case of a failure is a good thing. Redundancy in the form of backups is another good thing and all of these will assist you in keeping your job, but having multiple copies of the same data that are all being modified independently and not being synchronized is a nightmare.

The scenario for the 2013 Scripting Games Advanced Event #3 can be found here: http://scriptinggames.org/86122e78f3b1473045d1.pdf. I chose to first write a reusable function that would query the logical disk information and return it as generic objects that could be used to accomplish many different tasks. Want to create an HTML report as in this scenario, no problem. Want to display the output on the screen or place it in a text file, or use it as part of a larger project, those aren’t problems either, and there’s no reason to rewrite another function to retrieve the same information, ever. Hard coding this into the rest of the script or function is effectively the same thing and placing formatting cmdlets in you script or function because then you can’t do much else with it. What are you going to pipe the output to if it’s producing HTML files and not objects? Nothing, right? At least I can pipe format cmdlets to out cmdlets.

sg2013-event2a

Here’s the output of that function:

sg2013-event2b1

Note, I pulled the computer name from the computer with the other information. This is very important. Getting on my soapbox for a moment. What is PowerShell? Ultimately, it’s a means to an end. At the end of the day if you don’t accomplish the task at hand, it does not matter how perfect your PowerShell code is. The client, customer, or your boss won’t care that you did something really cool and used best practices because ultimately the code didn’t accomplish the task at hand. We should strive for all the above though, really cool, efficient code that accomplishes the goal your trying to accomplish and do it accurately!

Never depend on someone imputing the real computer name into your tool. It’s all too common to have a DNS CNAME record for many machines which is not the true computer name. The IP address or something such as localhost could also be provided. If you’re naming your HTML file and displaying the name that was provided via input on the webpage, there’s a good chance that it’s not the actual “Computer Name”. You’re already querying WMI and at least for the class I chose, Win32_LogicalDisk, the computer name can be retrieved from it as well so there’s not much overhead in retrieving one additional property to achieve a higher level of accuracy. Climbing off my soapbox now.

Ultimately, the Get-DiskInformation function would be placed in a separate module. You can see in the image below that I placed it in the begin block of my advanced script. Never heard of an advanced script? Neither had I. I didn’t even know you could do all those cool advanced function things in a script. Placing the Get-DiskInformation function in the process block would cause it to run one time for each computer that is piped in so don’t put it there because it only needs to be loaded once, then it’s in memory and can be called as many times as necessary without having to reload it.

While we’re on the subject of a script, you’re probably wondering why I chose a script instead of a function for this tool? Think about how it’s going to be used, read between the lines in otherwords. Is someone actually going to manually run this script? Probably not. How fast is the data going to be out of date? Possibly very quick since it’s a static HTML file. It’s probably going to be setup as a scheduled task. That said, if it were a function it would need a script or some code placed inside of the scheduled task to dot source it which could get messy. I thought it would be cleaner to have everything in a script that could be called using PowerShell.exe in task scheduler. To me that approach was cleaner.

Don’t forget about validating the path. That seems to be a common problem. I honestly didn’t know how to do that myself and I took a few hits in event 1 because of it. Here’s an article that Glenn Sizemore wrote that taught me how to validate those types of parameters.

sg2013-event2c

One small detail I did as well, as shown in the remainder of the script in the following image was to change the computer name to lower case for the output file because I prefer HTML files to be in lower case, but that’s just my personal preference. I didn’t change the case of the computer name that’s displayed on the web page though.

sg2013-event2d

Want to know more? I’m speaking this Saturday, May 18th on “PowerShell Fundamentals for Beginners” at SQL Saturday #220 in Atlanta.

Update 02/09/14
The link to my solution is no longer valid so I’m posting it here since I’ve received some requests for it:

This PowerShell script can also be downloaded from the TechNet script repository.

µ

Leave a Reply

%d bloggers like this: