When writing PowerShell scripts, one of the most time consuming tasks is validating input and handling invalid input. PowerShell does have built in mechanisms to deal with this and ease these tasks so that we can focus on creating a production level script.
Even if you’re new to PowerShell, you’ll have used some basic PowerShell cmdlets to probably get information. Sometimes you need to pass in parameters such as the ComputerName or a filter parameter. The scripts that you create or edit can also have parameters.
See the official Microsoft documentation on the About Functions at https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_functions
And of course, this blog post covers most of what is in the Advanced Functions at https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_functions_advanced_parameters
Common PowerShell Functions – NO Validation
When creating your script, think of it essentially as a giant function. The function name in this case would of course be the script name itself. Now that we can think of it as a function, we can also take advantage of passing in parameters. Also when we pass in the parameters we can have PowerShell validate them for us.
Stepping back a step, let’s just look at a function with three parameters. Pretty basic and simple function, but there is a lot we can do with it to clean it up to make it more robust.
function Write-TextToScreen { param ( $text, $ForegroundColor, $TimesToRepeat, $NoNewline ) 1..$TimesToRepeat | % { Write-Host -ForegroundColor $ForegroundColor -NoNewline:$NoNewline -Object $text } } Write-TextToScreen "Hello World" yellow 3 $false Write-Host "Testing Newline parameter"
The problem as I see it as there are some best practices lacking here. Yes, the parameters have some good names to signify what they are, but that’s it. Do I pass in numbers, strings, arrays? Also, what values am I allowed to pass in? For some reason I want to print the text out in the color of money. Is that possible? Silly as it may be, but yes we can according to our function definition, it’ll accept it!
PowerShell Features for Parameters
Problem 1
Now it’s time to learn and “lock” this code down. Let’s see what features PowerShell Provides. First off, we should always tell PowerShell what type of data the variables we’re defining. Let’s redefine the param section to include the type of data we will be storing. This ensures that whenever people call our script or function that they’ll pass in the correct type of data.
param ( [string]$text, [string]$ForegroundColor, [int]$TimesToRepeat, [boolean]$NoNewline )
Problem 2
If you look at the code a little closer, you’ll see that most of the parameters are passed to the Write-Host cmdlet. If a person called our function without passing in parameters, I’ll personally guarantee it will not print what you expected. What we can do here is add some default values to the function calls.
param ( [string]$text = "", [string]$ForegroundColor = "White", [int]$TimesToRepeat = 1, [boolean]$NoNewline = $false )
Problem 3
We have some defaults set so now we can just call the function and even put them in any order if we are passing them using the parameter names. The next problem is I really don’t know what color values I can use for the ForegroundColor. This problem comes up quite often! Read the documentation on what values you can pass, or you can self-document it a little and have PowerShell error check it for you at the same time! We do this by using the PowerShell feature called ValidateSet.
Let’s redefine the Foregroundcolor parameter t allow only 3 colors. Here I want to highlight that you can allow anything into the validation set, even spelling errors, so be careful! Why be careful with your validation? Well I figured I would allow and define a string value call MoneyGreen. Well this is all fine and dandy and it will work on a call to the function, but when the Write-Host cmdlet tries to print to the screen using the foreground color of MoneyGreen, it will then complain! Usually too far too late in your code. Let’s catch these errors before the function is called.
[ValidateSet("White", "Blue", "MoneyGreen")][string]$ForegroundColor = "White",
Solution
After tackling the 3 problems above the script looks like:
function Write-TextToScreen { param ( [string]$text = "", [ValidateSet("White", "Blue", "MoneyGreen")][string]$ForegroundColor = "White", [int]$TimesToRepeat = 1, [boolean]$NoNewline = $false ) 1..$TimesToRepeat | % { Write-Host -ForegroundColor $ForegroundColor -NoNewline:$NoNewline -Object $text } } Write-TextToScreen -TimesToRepeat 1 "Test" -ForegroundColor Blue Write-Host "Testing Newline parameter"
Other Parameter Validation Features
There are a few others, but I think you’ve gotten the idea of the blog post. Let’s validate the information at the start of the script or a function call before it starts. This allows us to properly define and call functions. It allows us to focus on the actual purpose of the script, not all the details of parameter checking and error handling. Let PowerShell do that for you!
Here is a list of advanced function attributes I commonly use throughout my scripts:
• [HelpMessage=”Parameter help information on how to use it”]
• [AllowNull()]
• [AllowEmptryString()]
• [AllowEmptyCollection]
• [ValidateNotNullOrEmpty]
• [ValidateNotNull]
• [Mandatory=$true|$false]
• [ValueFromPipeline=$true|$false]
• [ParameterSetName=”StringValue”]
• [Alias=(“alias1”, “alias2”)]
• [ValidateLenght(1,15)]
• [ValidatePattern(“SERVER\d{1,9}$”)]
• [ValidateRange(0,10)]
• [ValidateLength]
• [ValidateCount]
• [ValidateScript]