Summary: Microsoft Scripting Guy, Ed Wilson, shows how to use the Windows PowerShell Get-Command cmdlet to discover information about parameter sets.
Hey, Scripting Guy! One thing I don’t understand is parameter sets. I have heard about them, but I do not really find a good source of documentation about them. What is up with these things?
—BB
Hello BB,
Microsoft Scripting Guy, Ed Wilson, is here. Tonight is the night. At 9:30 PM Eastern Standard Time (-5 GMT) the two winners of the 2012 Scripting Games (Lido Paglia and Rohn Edwards), Jeffrey Snover, and myself appear with Jonathan Walz and Hal Rottenberg on the PowerScripting Podcast. This event is recorded live, and there is a chat room set up so you can talk to your fellow listeners and as ask questions of the guests. Last year it was a lot of fun, and it should be a lot of fun this year too. Jeffrey Snover is always very interesting to listen to, and he is a great guy to talk to.
Understanding parameter sets
BB, parameter sets are different ways of using a Windows PowerShell command. For example, there are three ways to use the Get-Process cmdlet. The one most everyone knows about is using Get-Process to obtain information about a process by passing it a name. In fact, this is the default parameter set, and you do not need to do anything special to use this parameter set.
Get-Process notepad
You can use the Get-Command cmdlet to provide information about the default parameter set for a cmdlet. The following commands retrieve the default parameter set for the Get-Process cmdlet.
PS C:\> $a = gcm Get-Process
PS C:\> $a.DefaultParameterSet
Name
To view the other parameter sets, you can query the ParameterSets property. As illustrated here, the Get-Process cmdlet has three different parameter sets.
PS C:\> $a = gcm Get-Process
PS C:\> $a.ParameterSets | select name
Name
----
Name
Id
InputObject
Now BB, you may ask, “What is the big deal with a parameter set?” For one thing, it provides different ways of working with the same command. In addition, it prevents potential errors. Refer back to the Get-Process cmdlet. An error would potentially arise if you specified that you wanted to see processes that had the name of calc.exe, but you specified a process ID that related to the notepad.exe process. Therefore, the name parameter set permits the name parameter, but excludes the id parameter. This is why, at times, you might see the following error message: Parameter set cannot be resolved…
As shown here, the message returns when you use parameters that when taken together, do not map to one specific parameter set.
One of the best ways to see the different parameter sets is to examine the output from the Get-Help cmdlet. Each parameter details separately. This is shown in the image that follows.
Working with Get-Command
One of the problems with the Get-Command cmdlet is that the command definition returns as “unstructured” text. But because you are working with Windows PowerShell, it is rather easy to correct this situation. The string data is shown here.
PS C:\> $a = gcm get-process
PS C:\> $a.Definition
Get-Process [[-Name] <String[]>] [-ComputerName <String[]>] [-Module] [-FileVersionI
nfo] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPr
eference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <Stri
ng>] [-OutBuffer <Int32>]
Get-Process -Id <Int32[]> [-ComputerName <String[]>] [-Module] [-FileVersionInfo] [-
Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreferenc
e>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-
OutBuffer <Int32>]
Get-Process [-ComputerName <String[]>] [-Module] [-FileVersionInfo] -InputObject <Pr
ocess[]> [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <Acti
onPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <
String>] [-OutBuffer <Int32>]
When attempting to index into the parameter set, individual letters return. This problem appears here.
PS C:\> $a.Definition[0]
G
But using the Split operator turns the output into an array. The `r character is a special character that represents a carriage return. By splitting on these carriage returns, an array with three elements returns to the Windows PowerShell command prompt as shown here.
PS C:\> $a.Definition -split "`r"
Get-Process [[-Name] <String[]>] [-ComputerName <String[]>] [-Module] [-FileVersionI
nfo] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPr
eference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <Stri
ng>] [-OutBuffer <Int32>]
Get-Process -Id <Int32[]> [-ComputerName <String[]>] [-Module] [-FileVersionInfo] [-
Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreferenc
e>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-
OutBuffer <Int32>]
Get-Process [-ComputerName <String[]>] [-Module] [-FileVersionInfo] -InputObject <Pr
ocess[]> [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <Acti
onPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <
String>] [-OutBuffer <Int32>]
Storing the output in a variable makes it easy to index into the array and retrieve a specific parameter set. This technique appears here.
PS C:\> $gps = $a.Definition -split "`r"
PS C:\> $gps[0]
Get-Process [[-Name] <String[]>] [-ComputerName <String[]>] [-Module] [-FileVersionI
nfo] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPr
eference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <Stri
ng>] [-OutBuffer <Int32>]
PS C:\> $gps[1]
Get-Process -Id <Int32[]> [-ComputerName <String[]>] [-Module] [-FileVersionInfo] [-
Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <ActionPreferenc
e>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <String>] [-
OutBuffer <Int32>]
PS C:\> $gps[2]
Get-Process [-ComputerName <String[]>] [-Module] [-FileVersionInfo] -InputObject <Pr
ocess[]> [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-WarningAction <Acti
onPreference>] [-ErrorVariable <String>] [-WarningVariable <String>] [-OutVariable <
String>] [-OutBuffer <Int32>]
The ParameterSetInfo object
In addition to working with the definition of a Windows PowerShell cmdlet, the ParameterSets property contains an array of CommandParameterSetInfo objects. The following command stores the object in a temporary variable, and then displays the members of the CommandParameterSetInfo object.
PS C:\> $a = get-command get-process
PS C:\> $a.ParameterSets | gm
TypeName: System.Management.Automation.CommandParameterSetInfo
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
IsDefault Property System.Boolean IsDefault {get;}
Name Property System.String Name {get;}
Parameters Property System.Collections.ObjectModel.ReadOnlyCollection`1[[Syste...
Because the ParameterSets property returns a collection, it is possible to index directly into the collection and return information from it. However, indexing into the collection produces an output that seems a bit strange. This output is shown in the image that follows.
When you pipe a single instance of the ParameterSets to the Get-Member cmdlet, everything still appears to be in the Parameters property. Therefore, it is time to use one of my favorite tricks (see favorite trick #3)—the ExpandProperty parameter from the Select-Object cmdlet. After I do this, everything falls into place. The two commands I use are shown here.
$a = get-command get-process
$a.ParameterSets[0] | select -ExpandProperty parameters
The commands, and the associated output are shown here.
Now it is trivial to see all of the parameters that are associated with a specific parameter set. In addition, the parameter aliases appear.
Note For more information about parameter aliases, see Weekend Scripter: Discovering PowerShell Cmdlet Parameter Aliases.
PS C:\> $a = get-command get-process
PS C:\> $a.ParameterSets[0] | select -ExpandProperty parameters | ft name, ismandator
y, aliases
Name IsMandatory Aliases
---- ----------- -------
Name False {ProcessName}
ComputerName False {Cn}
Module False {}
FileVersionInfo False {FV, FVI}
Verbose False {vb}
Debug False {db}
ErrorAction False {ea}
WarningAction False {wa}
ErrorVariable False {ev}
WarningVariable False {wv}
OutVariable False {ov}
OutBuffer False {ob}
BB, that is all there is to working with parameter sets. Join me tomorrow for more Windows PowerShell cool stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy