Lately, it seems every Windows IT administrator has been compelled to write PowerShell scripts. It could be something they found an example of online, a Frankenstein combination of parts and pieces of other scripts, or something they read in a book and want to try. Everybody's script library starts as parts and pieces, and as you learn more PowerShell, you will find these useful tips to help write better scripts.
Everything Will Fail
First, assume everything you write will fail. What I mean by that, is that even with something as simple as "Import- Csv-Path "C:\Temp\computer_list.csv", you should assume that something will go wrong eventually.
- Maybe it works on your computer but not on another computer because there is no "Temp" folder.
- Maybe the person running the script doesn't have access to the file.
- Maybe someone moves the file or renames it.
Whatever the case, assume that each line of code may fail. So, how do you plan for and work around errors? By using a Try/Catch block of code. In other words, try something, and if it fails, catch the error.
What does that look like in PowerShell?
In this example, it should import the CSV file, but if it can't, the script will send the screen a message and then stop. The Try/Catch block is a tool that can do a lot of things, and the examples here only scratch the surface. If you run the above script, the only thing that will display is, "Cannot Import CSV File."
Let's look at another example of Try/Catch where we will divide one by zero, but this time, if it fails, it should show me all the information about the error.
Click image to enlarge.
Note: The "$_" is the current object variable and represents the error object being passed into the Catch block.
When you run the above code, a lot of information will display on the screen, and you’ll see a few interesting things in the error message:
- The exception type, which means you could give different actions based on the specific error
- The exception friendly message
- Where the error occurred
How can we make the output a little friendlier when errors occur? By wrapping the current object variable in a pair of double quotes, like this:
Notice how the error message shows a user-friendly output of the error message. That means we can add more messages about what happened. Let's look at our earlier example of getting a file and add a better error message to the output.
Isn't the output a little nicer to read? It also doesn't assume that the file will always be there. Whatever the error message, it will provide an example of why it failed.
Improving Scripts with Formatting
Now, let's look at four cmdlets we can use to improve our scripts:
- Write-Output sends the specified object down the pipeline to the next command. If the command is the last command in the pipeline, the object is displayed in the console.
- Write-Host customizes output. You can specify the color of text and you can specify the background color.
- Write-Warning writes a warning message.
- Write-Error writes an object to the error stream.
Just adding "Write-Output" to our script will still display information to the screen as before, so there's not much to be amazed with on this example.
However, we can add color to the output messages by using "Write-Host".
Note: I don't usually use "Write-Host" unless I'm writing a script that will only be used in an interactive PowerShell session.
Now, if we create the file and try again, you can see what happens when it finds the file.
Same script, but green is good, right?
Stopping Versus Informing
Let's look at the difference between an error that should stop the script immediately and an error that only needs to notify that something went wrong, but the script may continue to keep going.
Let’s first look at the warning message that won't stop the script, but only show a message that something did not go as expected.
You'll notice that, in the warning, it tells you there is a warning, but it doesn't stop the script. I didn't have to tell the computer to change the color or add the title, that is just what the cmdlet "Write-Warning" does.
What about "Write-Error"? What will that do?
Note: Up to this point, I have been running commands interactively, but now I'm going to save my script at "C:\Temp\Part1.ps1". When I run the script next time, it will show the name of the script that had the error and all the information about the error.
Notice that it didn't stop the script and we still see the "Next thing." It did, however, change the output to red and give a lot of information about what happened and why. But, what if I want the script to stop? Simply adding the parameter "ErrorAction" with a value of "Stop" to the "Write-Error" cmdlet will stop the script.
This time, the script will stop after the error. You will not see the "Next thing."
For errors that should stop the script, this is a great thing.
I also always use the cmdlet “Write-Verbose” but I’ll share that in the next post, when we talk about CmdletBinding and adding personalized help for your scripts.
In my experience with helping other administrators troubleshoot their PowerShell scripts, I’ve found that adding Try/Catch blocks is a great way to figure out what is and is not working.
CompTIA certifications validate IT skills from the help desk to top security professionals. Learn more about CompTIA certifications.
Donald Jacobs began his IT career back when Windows NT was the biggest and best new technology in the field. Since that time, he has earned a multitude of Microsoft certifications, including MCSA Windows Server 2016, MCSE Server Infrastructure 2012, MCSA Office 365, MCITP Enterprise Administrator 2008 and MCTS for Windows 7. He has taught Microsoft’s Certified PowerShell and Windows Server courses as a Microsoft Certified Trainer. Donald co-authored the book, Troubleshooting Windows Server with PowerShell. He currently supports clients and customers with Microsoft products, particularly PowerShell, Azure, Office 365, Active Directory, Exchange and Windows Server.