Examining cmdlet parameters in PowerShell V2

One of the interesting things about PowerShell is how easy it is to discover its cmdlets and parameter. In PowerShell itself or in the ISE, you can just start typing a command and then press the <TAB> key complete it.

One other interesting bit is how you can use the Get-Command cmdlet to discover all others. I covered some of this functionality and the ability to load modules in a previous blog post at https://blogs.technet.com/josebda/archive/2009/08/09/experimenting-with-powershell-cmdlets-snap-ins-and-modules.aspx

For example, Get-Command can easily help you find all the cmdlets related to the EventLogs:

PS C:\> Get-Command -Noun EventLog

CommandType Name Definition
----------- ---- ----------
Cmdlet Clear-EventLog Clear-EventLog [-LogName] <String[]> [[-Computer...
Cmdlet Get-EventLog Get-EventLog [-LogName] <String> [[-InstanceId] ...
Cmdlet Limit-EventLog Limit-EventLog [-LogName] <String[]> [-ComputerN...
Cmdlet New-EventLog New-EventLog [-LogName] <String> [-Source] <Stri...
Cmdlet Remove-EventLog Remove-EventLog [-LogName] <String[]> [[-Compute...
Cmdlet Show-EventLog Show-EventLog [[-ComputerName] <String>] [-Verbo...
Cmdlet Write-EventLog Write-EventLog [-LogName] <String> [-Source] <St...

Is it also just as simple to find all cmdlets that Format the output. The next examples uses “gcm”, the alias for Get-Command:

PS C:\> gcm -Verb Format

CommandType Name Definition
----------- ---- ----------
Cmdlet Format-Custom Format-Custom [[-Property] <Object[]>] [-Depth <...
Cmdlet Format-List Format-List [[-Property] <Object[]>] [-GroupBy <...
Cmdlet Format-Table Format-Table [[-Property] <Object[]>] [-AutoSize...
Cmdlet Format-Wide Format-Wide [[-Property] <Object>] [-AutoSize] [...

Now what I was looking into recently was not no much the cmdlets but the parameters you can use with them.

For instance, which cmdlets take “-ComputerName” as a parameter? That’s quite easy to answer if you look at the Definition of the command. Here’s what you can use for that:

PS C:\> Get-Command -type cmdlet | Where {$_.Definition -like "*-ComputerName*"}

CommandType Name Definition
----------- ---- ----------
Cmdlet Clear-EventLog Clear-EventLog [-LogName] <String[]> [[-Computer...
Cmdlet Connect-WSMan Connect-WSMan [[-ComputerName] <String>] [-Appli...
Cmdlet Disconnect-WSMan Disconnect-WSMan [[-ComputerName] <String>] [-Ve...
Cmdlet Enter-PSSession Enter-PSSession [-ComputerName] <String> [-Crede...
Cmdlet Get-Counter Get-Counter [[-Counter] <String[]>] [-SampleInte...
Cmdlet Get-EventLog Get-EventLog [-LogName] <String> [[-InstanceId] ...
Cmdlet Get-HotFix Get-HotFix [[-Id] <String[]>] [-ComputerName <St...
Cmdlet Get-Process Get-Process [[-Name] <String[]>] [-ComputerName ...
Cmdlet Get-PSSession Get-PSSession [[-ComputerName] <String[]>] [-Ver...
Cmdlet Get-Service Get-Service [[-Name] <String[]>] [-ComputerName ...
Cmdlet Get-WinEvent Get-WinEvent [[-LogName] <String[]>] [-MaxEvents...
Cmdlet Get-WmiObject Get-WmiObject [-Class] <String> [[-Property] <St...
Cmdlet Get-WSManInstance Get-WSManInstance [-ResourceURI] <Uri> [-Applica...
Cmdlet Invoke-Command Invoke-Command [-ScriptBlock] <ScriptBlock> [-In...
Cmdlet Invoke-WmiMethod Invoke-WmiMethod [-Class] <String> [-Name] <Stri...
Cmdlet Invoke-WSManAction Invoke-WSManAction [-ResourceURI] <Uri> [-Action...
Cmdlet Limit-EventLog Limit-EventLog [-LogName] <String[]> [-ComputerN...
Cmdlet New-EventLog New-EventLog [-LogName] <String> [-Source] <Stri...
Cmdlet New-PSSession New-PSSession [[-ComputerName] <String[]>] [-Cre...
Cmdlet New-WSManInstance New-WSManInstance [-ResourceURI] <Uri> [-Selecto...
Cmdlet Receive-Job Receive-Job [-Job] <Job[]> [[-Location] <String[...
Cmdlet Register-WmiEvent Register-WmiEvent [-Class] <String> [[-SourceIde...
Cmdlet Remove-EventLog Remove-EventLog [-LogName] <String[]> [[-Compute...
Cmdlet Remove-PSSession Remove-PSSession [-Id] <Int32[]> [-Verbose] [-De...
Cmdlet Remove-WmiObject Remove-WmiObject [-Class] <String> [-AsJob] [-Im...
Cmdlet Remove-WSManInstance Remove-WSManInstance [-ResourceURI] <Uri> [-Sele...
Cmdlet Restart-Computer Restart-Computer [[-ComputerName] <String[]>] [[...
Cmdlet Set-Service Set-Service [-Name] <String> [-ComputerName <Str...
Cmdlet Set-WmiInstance Set-WmiInstance [-Class] <String> [[-Arguments] ...
Cmdlet Set-WSManInstance Set-WSManInstance [-ResourceURI] <Uri> [[-Select...
Cmdlet Show-EventLog Show-EventLog [[-ComputerName] <String>] [-Verbo...
Cmdlet Stop-Computer Stop-Computer [[-ComputerName] <String[]>] [[-Cr...
Cmdlet Test-Connection Test-Connection [-ComputerName] <String[]> [[-So...
Cmdlet Test-WSMan Test-WSMan [[-ComputerName] <String>] [-Authenti...
Cmdlet Write-EventLog Write-EventLog [-LogName] <String> [-Source] <St...

For the next few examples, please start PowerShell with the option to “Import System Modules”. This is easy to do if you pin the “PowerShell” program to the taskbak and then start it with a right-click: 

Import System Modules

In that case, PowerShell will take a little longer to start, but it will load all the system modules. How many additional ones? Well, you can use Get-Command to figure out just that:

PS C:\> Get-Command -type cmdlet | Group Module | Sort Count -Desc

Count Name Group
----- ---- -----
242 {Add-Computer, Add-Content, Add-History, Add-Member...}
76 ActiveDirectory {Add-ADComputerServiceAccount, Add-ADDomainControllerPasswordReplicationPolicy, Add-...
71 WebAdministration {Add-WebConfiguration, Add-WebConfigurationLock, Add-WebConfigurationProperty, Backu...
69 FailoverClusters {Add-ClusterDisk, Add-ClusterFileServerRole, Add-ClusterGenericApplicationRole, Add-...
25 GroupPolicy {Backup-GPO, Copy-GPO, Get-GPInheritance, Get-GPO...}
8 BitsTransfer {Add-BitsFile, Complete-BitsTransfer, Get-BitsTransfer, Remove-BitsTransfer...}
5 AppLocker {Get-AppLockerFileInformation, Get-AppLockerPolicy, New-AppLockerPolicy, Set-AppLock...
2 TroubleshootingPack {Get-TroubleshootingPack, Invoke-TroubleshootingPack}

Now, with that in mind, you could also start to look into what parameters are use with the commands from each module.
For instance, you can look at which modules most implement the “-WhatIf” parameter:

PS C:\> Get-Command -type cmdlet | Where {$_.Definition -like "*-WhatIf*"} | Group Module

Count Name Group
----- ---- -----
53 ActiveDirectory {Add-ADComputerServiceAccount, Add-ADDomainControllerPasswordReplicationPolicy, Add-...
7 BitsTransfer {Add-BitsFile, Complete-BitsTransfer, Remove-BitsTransfer, Resume-BitsTransfer...}
85 {Add-Computer, Add-Content, Clear-Content, Clear-EventLog...}
28 WebAdministration {Add-WebConfiguration, Add-WebConfigurationLock, Add-WebConfigurationProperty, Clear...
17 GroupPolicy {Backup-GPO, Copy-GPO, Import-GPO, New-GPLink...}
14 FailoverClusters {Block-ClusterAccess, Clear-ClusterDiskReservation, Clear-ClusterNode, Remove-Cluste...
1 AppLocker {Set-AppLockerPolicy}

Or you you might want to look into which modules contain more of a specific type of verb, noun or parameter. For instance, if you’re looking for a cmdlet to manager users, you could try:

PS C:\> gcm -type cmdlet| ?{$_.Definition -like "*user*"} | Select Module, Name | Group Module | Sort Count -Desc

Count Name Group
----- ---- -----
8 ActiveDirectory {@{Module=ActiveDirectory; Name=Get-ADUser}, @{Module=ActiveDirectory; Name=Get-ADUs...
4 FailoverClusters {@{Module=FailoverClusters; Name=Block-ClusterAccess}, @{Module=FailoverClusters; Na...
3 {@{Module=; Name=Get-EventLog}, @{Module=; Name=Invoke-Sqlcmd}, @{Module=; Name=Star...
2 AppLocker {@{Module=AppLocker; Name=New-AppLockerPolicy}, @{Module=AppLocker; Name=Test-AppLoc...
2 BitsTransfer {@{Module=BitsTransfer; Name=Get-BitsTransfer}, @{Module=BitsTransfer; Name=Set-Bits...
1 GroupPolicy {@{Module=GroupPolicy; Name=Get-GPResultantSetOfPolicy}}

Now, saving the best for last, we could try to understand which parameters are used the most. This is a tricky one-liner, since we need to look into the definition itself then do some pattern matching, string splitting and comparison to isolate the parameters. We finally pass each individual one into the pipelining for further grouping and sorting, limiting to the 40 parameters most used. On the split, we split on spaces, open brackets “\[“ or close bracets “\]”, using the \ as a escape character since [ and ] are special characters for pattern matching.

PS C:\> gcm -type cmdlet | % { $d=$_.Definition -Split "[ \[\]]"; for ($c=1; $c -lt $d.count; $c++) { If ($d[$c][0] -eq "-") { $d[$c] } } } | Group | Sort Count -Desc | Select Count, Name -First 40

Count Name
----- ----
786 -Debug
786 -Verbose
786 -OutBuffer
786 -ErrorVariable
786 -WarningAction
786 -OutVariable
786 -WarningVariable
786 -ErrorAction
318 -Confirm
318 -WhatIf
233 -Credential
226 -Name
165 -Server
146 -Force
142 -InputObject
139 -PassThru
115 -AuthType
90 -Path
73 -Filter
73 -UseTransaction
72 -Exclude
71 -Include
71 -Identity
69 -ComputerName
64 -Cluster
49 -Authentication
48 -Domain
41 -Partition
36 -PSPath
35 -ThrottleLimit
32 -AsJob
31 -LiteralPath
29 -Namespace
28 -Value
28 -Description
27 -Location
26 -DisplayName
25 -ArgumentList
25 -Properties
24 –Impersonation

You can see that the “common parameters” are obvious on the top of the list, followed by a few popular ones like “-Credential”, “-Name” and “-Server”.

Hope you learned something new and have fun with PowerShell...