Introducing the ScriptingHelp PowerShell Module

Over the last few weeks I’ve posted articles on the different parameter validation options in Windows PowerShell. More than one person suggested consolidating the articles. That seemed like a good idea. There were a variety of ways to handle this but I wanted something more PowerShell-oriented. Then I realized, why not produce PowerShell About topics? I could create a module that primarily was a collection of about topics on scripting in PowerShell. Import the module and you get the documentation.

In fact, this is a slick idea you might want to take advantage of: create a PowerShell module with nothing but documentation delivered via About_* files. If you are spending a lot of time in the shell, stay there! But before I get sidetracked, let’s look at the module I’m calling ScriptingHelp.

As I said the module is mostly a collection of About_* topics based on some of my blog articles. Then I realized I wanted to make it easier to expose them so I threw together a brief function called Get-ScriptingHelp.

The About topics are edited and revised versions of material previously posted on my blog.

I plan on contributing additional content over time based on previous blog articles, suggestions or anything that comes to mind that I think can help you write more effective PowerShell scripts and functions.

To that end, I have also included a function to help you start scripting even faster. It is a new function wizard called Invoke-FunctionWizard. When you run the wizard, you will be prompted for information about your new function such as its name and parameter information. The wizard will then write a string object with the skeletal outline of your new function, complete with comment-based help. If you run the wizard in the ISE it will automatically insert the text into the currently open file.

But perhaps you’d like to see all of this in action.

I hope you’ll let me know what you think and if you find this useful or worthy of continued development. You can download a zip file of ScriptingHelp_0_9. Extract the folder as a subfolder under C:\Users\\Documents\WindowsPowerShell\Modules. Then import the ScriptingHelp module. This should work in both the console and the PowerShell ISE. Enjoy!

PowerShell Scripting with [ValidateNotNullorEmpty]

I’ve been writing about the different parameter validation attributes that you can use in your PowerShell scripting. One that I use in practically every script is [ValidateNotNullorEmpty()]. This validation will ensure that something is passed as a parameter value. I’m not talking about making a parameter mandatory; only that if the user decides to use the parameter that something is passed. Let’s look at my demo.


#requires -version 2.0

Param (
[Parameter(Position=0,Mandatory=$True,HelpMessage="Enter a process name like lsass")]
[ValidateNotNullorEmpty()]
[string]$Name,
[Parameter(Position=1)]
[ValidateNotNullorEmpty()]
[string]$Computername=$env:computername

)

Try {
Get-Process -Name $name -ComputerName $computername -errorAction "Stop" | Select *,
@{Name="Runtime";Expression={(Get-Date)-$_.StartTime}}
}

Catch {
Write-Warning $_.Exception.Message
}

I’ve used the attribute on both parameters. The first parameter I’ve also made mandatory which makes it more likely that something will be entered. But if not, then the script will fail.

I would get a similar message if the user forgot to complete the command.

Even though I’m using a default value for Computername, as soon as the parameter is detected PowerShell assumes I’m going to use a different value.

Validation should work for missing values, a variable that might be null, or in general anything that is meaningless. However, it won’t prevent something quirky like this:


PS S:\> $p=" "
PS S:\> .\demo-ValidateNotNull.ps1 -name $p
WARNING: Cannot find a process with the name " ". Verify the process name and
call the cmdlet again.

The variable, while semantically meaningless to us, is not null or empty but a string of 1 space. If there’s the chance you might run into this situation then you can add additional validation checks to the parameter.

If you’d like, feel free to download Demo-ValidateNotNull and see for yourself.

PowerShell Scripting with [ValidateCount]

Here’s another parameter validation attribute you might want to use in your PowerShell scripting and functions. If your parameter can take an array of values, you might want to limit that array to a certain size. For example, your parameter can take an array of computer names but you don’t want to process more than 5 for some reason. This is where [ValidateCount()] comes in to play.

This attribute takes two values, the minimum number of accepted parameter values and the maximum.


[ValidateCount(1,10)]
[string[]]$Computername

If used, this would mean I would need at least one computername but no more than 10. You could also set both values the same if you wanted an exact number:


[ValidateCount(2,2)]
[int[]]$Numbers

Now, I’d have to pass exactly 2 numbers as parameter values. Let’s look at a more complete example.


#requires -version 2.0

Param (
[Parameter(Position=0,Mandatory=$True)]
[ValidateCount(1,5)]
[string[]]$Name
)

Foreach ($item in $name) {

#display the name in a random color
Write-Host $item -ForegroundColor ([system.consoleColor]::GetValues("system.consolecolor") | get-random)

}

This simple script writes each name in a random color, assuming I pass no more than 5 names.

If I exceed that count, PowerShell will throw a tantrum (I mean exception).

When you use this validation test, be sure your parameter is set to accept an array of values, e.g. [string[]]. If you’d like to try out my sample code feel free to download Demo-ValidateCount.

PowerShell Scripting with [ValidatePattern]

I’ve been writing about a number of parameters attributes you can include in your PowerShell scripting to validate parameter values. Today I want to cover using a regular expression pattern to validate a parameter value. I’m going to assume you have a rudimentary knowledge of how to use regular expressions in PowerShell. If not, there is an entire chapter devoted to the topic in Windows PowerShell 2.0: TFM.

The parameter attribute is [ValidatePattern()]. Inside the parentheses you place a scriptblock with the regular expression pattern. For example, in PowerShell we might write a command like this to verify if something is a number of 1 to 3 digits.:


$x -match "^\d{1,3}$"

To use that pattern in a [ValidatePattern()] attribute, you would write it like this:


[ValidatePattern({^\d{1,3}$})]

There is no need to use the -match operator or $_. Sure, I suppose you could write a validation script to achieve the same effect, but this is just as easy. I recommend testing your pattern from the PowerShell prompt, especially testing for failures. Here’s a more complete example.

Param (
[Parameter(Position=0,Mandatory=$True,HelpMessage="Enter a UNC path like \\server\share")]
[ValidatePattern({^\\\\\S*\\\S*$})]
[ValidateScript({Test-Path -Path $_ })]
[string]$Path
)

Write-Host "Getting top level folder size for $Path" -ForegroundColor Magenta
dir $path | measure-object -Property Length -sum

For you regular expression gurus, don’t get hung up on my pattern. It works for my purposes of illustration. Your pattern can be as simple or as complex as you need it to be. In this short script I’m expecting a path value like \\file01\public. If the value is not in this format, the pattern validation will fail, PowerShell will throw an exception and the script will fail.

Notice I’m also using a second parameter validation attribute, [ValidateScript()]. It is possible for the pattern to be correct but invalid so I can combine both validation tests.


PS C:\> S:\Demo-ValidatePattern.ps1 '\\file01\temp'
C:\scripts\Demo-ValidatePattern.ps1 : Cannot validate argument on parameter 'Pa
th'. The "Test-Path -Path $_ " validation script for the argument with value "\
\file01\temp" did not return true. Determine why the validation script failed a
nd then try the command again.
At line:1 char:28
+ S:\Demo-ValidatePattern.ps1 <<<< '\\file01\temp' + CategoryInfo : InvalidData: (:) [Demo-ValidatePattern.ps1], Par ameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,Demo-ValidatePa ttern.ps1

If you'd like to try out my sample script, you can download it here.

PowerShell Scripting with [ValidateSet]

Today we’ll continue our exploration of the parameter validation attributes you can use in you PowerShell scripting. We’ve already looked at [ValidateRange] and [ValidateScript]. Another attribute you are likely to use is [ValidateSet()]. You can use this to verify that the parameter value belongs to a pre-defined set.

To use, specify a comma separated list of possible values.

If the person running the script specifies something other than “Apple”, “Banana”, or “Cherry” as a value for -Fruit, PowerShell will throw an exception and the script will fail to run. And in case you were wondering, this is not case-sensitive.

If you are going to use this attribute, I recommend providing documentation either in comment based help and/or as part of a help message so the user knows what values to expect. The PowerShell help system doesn’t automatically detect this attribute and use it in syntax display as you might have seen with other cmdlets.

Here’s a more practical example.

The script will get recent events from a specified log on a specified computer and export the results. My script will only export from a short list of logs which I’m validating.

If an invalid value is detected PowerShell will complain.

The error message displays the expected values, but the better approach might be to include them in a help message, especially if the parameter is mandatory. For example, this script will export results based on -Export.

If you’d like to try out my demo script, you can download Demo-ValidateSet.