Want to write an Advanced Function ("script cmdlet?") Here's how.

I'm off to speak at the Wisconsin IT Symposium this week, so I thought I'd offer a beefy article to tide you over.

This isn't meant to be so much a USEFUL Advanced Function as it is an all-in-one demo of what Advanced Functions can look like. Notice:
  • Comment-based help, producing properly-formatted help when you run "Help Get-Info"
  • Support for -whatif and -confirm parameters (added by "SupportsShouldProcess()")
  • Support for ByValue and ByPropertyName parameter binding of pipeline input
There are some additional examples at the end; remove those and save this as a .psm1 file to create a Script Module!

I'll have several upcoming articles about how to construct this type of function... just wanted to share the final product in the meantime :). 

03.Retrieves operating system and BIOS information from one or more remote computers.
05.Get-Info retrieves operating system and service pack version information, along with BIOS serial number information, from one or more remote computers. It uses WMI to retrieve this information, so the appropriate firewall ports must be opened.
07.The output objects have properties for OS Version, OS Build Number, Service Pack version, and BIOS Serial Number. The computer name is also included in its own property.
09.Because WMI is used, computers are processed sequentially. Unreachable computers will incur a timeout of approximately 30 seconds.
11.Bind pipeline input by value
12.'localhost','win-por9tp458l7','not-online' | Get-Info
14.Use parameter
15.Get-Info -computername 'localhost' -errorlog 'errors.txt'
17.Bind pipeline input ByPropertyName - assumes CSV file has a "computername" column
18.Import-Csv inventory.csv | Get-Info -errorlog 'retries.txt'
19..PARAMETER ComputerName
20.One or more computer names.
21..PARAMETER ErrorLog
22.Path and filename where you wish unreachable computer names to be logged.
23..PARAMETER ErrorBehavior
24.'Log' or 'Ignore,' depending on what you want to happen when a computer cannot be reached.
26.function Get-Info {
27.    [CmdletBinding()]
28.    param(
29.        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,HelpMessage='Computer name(s) to target')]
30.        [string[]]$computername,
32.        [Parameter(HelpMessage='Path and filename of file for unreachable computer names')]
33.        [string]$errorlog = 'unreachable.txt',
35.        [Parameter(HelpMessage='What to do when connection errors occur')]
36.        [ValidateSet('Log','Ignore')]
37.        [string]$errorbehavior = 'Log'
38.    )
39.    BEGIN {
40.        del $errorlog -erroraction 'SilentlyContinue'
41.    }
42.    PROCESS {
43.        try {
44.            $skip = $false
45.            $os = Get-WmiObject win32_operatingsystem -ComputerName $computername -ErrorAction 'Stop'
46.            $bios = Get-WmiObject win32_bios -ComputerName $computername -ErrorAction 'Stop'
47.        } catch {
48.            $skip = $true
49.            if ($errorbehavior -eq 'Log') {
50.                $computername | Out-File $errorlog -append
51.            }
52.        }
53.        if (-not $skip) {
54.            $obj = New-Object PSObject
55.            $obj | Add-Member NoteProperty ComputerName $computername
56.            $obj | Add-Member NoteProperty OSVersion ($os.caption)
57.            $obj | Add-Member NoteProperty OSBuild ($os.buildnumber)
58.            $obj | Add-Member NoteProperty SPVersion ($os.servicepackmajorversion)
59.            $obj | Add-Member NoteProperty BIOSSerial ($bios.serialnumber)
60.            Write-Output $obj
61.        }
62.    }
63.    END {}
66.# bind pipeline input by value
67.'localhost','win-por9tp458l7','not-online' | Get-Info
69.# use parameter
70.Get-Info -computername 'localhost' -errorlog 'errors.txt'
72.# bind pipeline input ByPropertyName
73.# assumes CSV file has a "computername" column
74.Import-Csv inventory.csv | Get-Info -errorlog 'retries.txt'

Discuss this Blog Entry 3

Bartek B (not verified)
on May 2, 2010
I tend to forget about this: "use get-help to get help". ;) In fact reading it exposed more parameter options I haven't even seen in MSDN (or I've overlooked it). Thanks! :)
Bartek B (not verified)
on Apr 27, 2010
Thanks A LOT for that post. It really pushed me in the direction of writing scripts that behave (almost) like cmdlets. Do you happen to know a good page where all those .CAPITALS and [parameter(options)] (besides msdn that covers mainly C# if I'm not mistaken)? I would really love to play with this syntax a bit.
on Apr 30, 2010
You bet: run "help about_comment_based_help" in PowerShell itself to get the syntax for the help, and "help about *advanced*" for information on advanced functions (which I lovingly call "script cmdlets") and their parameters.

Please or Register to post comments.

What's PowerShell with a Purpose Blog?

Don Jones demystifies Windows PowerShell.

Blog Archive

Sponsored Introduction Continue on to (or wait seconds) ×