How To Write Better PowerShell Scripts
As with most things, approaching it with a sound plan will save you time and effort.
- By Adam Bertram
PowerShell has made it dead simple to automate all kinds of things. However, its simplicity can be deceiving. PowerShell takes the complexity out of script writing but unless you're writing a one-liner, it's important to first think of the problem you're going to solve before you start coding. If not, you'll spend 10 times the time and come away with a script that's much less efficient than if you would have just taken a few minutes to lay out the structure ahead of time.
You wouldn't just hire a freelancer to help you out with an annoying task without first providing them with a clear set of instructions. Think about this before beginning to write a script that you know will require a significant effort.
There's a couple informal planning steps I do prior to writing a single line of code for a potentially large PowerShell scripts.
Describe the Script in One Sentence
Let's say I want to build a script that periodically reads the event log of a server for a specific event. When that event is found, restart a service on another server and send an e-mail. I've already accomplished the first phase in planning. I've accurately described, on a high level, what the script should do.
You might think this is obvious but think back on all the scripts you've written in the past that have changed dramatically from inception to final product. Was the initial idea in your head actually what you intended? Probably not. You'd be surprised after you make a conscious effort to describe what you want the script to do that your initial idea changes.
Pseudocode Is Your Friend
You've got your future script described in a sentence. It's now time to put some meat behind it. Before you write a single line of code write the entire script in pseudocode. Pseudocode is a method that developers use to plan out a software application in plain english. It is a great way to force yourself to think of the details ahead of time. Pseudocode is not a specific language; it's just a way to get the flow of your script down before you actually start writing code.
Here's some example pseudocode for our fictional example script.
(Check every 10 minutes with a scheduled task)
if server X is available and events can be queried then
Enumerate events in the application log of server X within the last 10 minutes
If event ID 4665 is found then
If server Y is online and service Z is still on it then
Restart service Z
Log the success
If we can use our SMTP service to send an email then
Log email sent
Log email not able to be sent
Write to a log that server Y or service Z was unavailable
Log that event ID 4665 was not found
Log that server X wasn't available
Notice that this not a specific language. It was just an easy way for me to brainstorm how I envision the script running. It contains a lot of conditions (if/then/else) statements. As I was working through this my mind was constantly thinking of things on the fly that I never thought of when I wrote out my description sentence. I was forced to think that I needed to create a scheduled task and how often I wanted it to run, the specific event ID I wanted to look for, what to do if the script wasn't able to run for some reason (error control) and I thought to add logging functionality as I was working through it. I never considered these details prior to going through this exercise.
Pseudocode also makes your functions stand out as well. It's always a good idea to group a specific task into a function. Some functions that might come out of this could be
Test-ServerXAvailable which could include a quick ping test and that you had permission to access the Application event log,
Write-Log that might include a date timestamp of when something happened and the message,
Test-Email to first check if the SMTP server we're using has SMTP port 25 available and perhaps ` ` which contained the SMTP server you'll be using, the from address and the To address.
I've found that describing your script and writing out some pseudocode like this ahead of time will save you tons of time in the long run. I challenge you to try this sometime before starting on a new script and time yourself. Try to keep mental count of all the details you didn't think of ahead of time and just how many other ideas pop into your head while going through this process. I promise you that script you thought would be a piece of cake looks much more involved once you actually step through it.
Adam Bertram is an independent consultant, technical writer, trainer and presenter. Adam specializes in consulting and evangelizing all things IT automation mainly focused around Windows PowerShell. Adam is a Microsoft Windows PowerShell MVP, 2015 powershell.org PowerShell hero and has numerous Microsoft IT pro certifications. He is a writer, trainer and presenter and authors IT pro course content for Pluralsight. He is also a regular contributor to numerous print and online publications and presents at various user groups and conferences. You can find Adam at adamtheautomator.com or on Twitter at @adbertram.