PoshCode Logo PowerShell Code Repository

Get-Parameter 2.4 (modification of post by Joel Bennett view diff)
diff | embed code: <script type="text/javascript" src="http://PoshCode.org/embed/2032"></script>download | new post

This is another Must Have upgrade, because I screwed up the last one ;-)

  1. #Requires -version 2.0
  2.  
  3. #.Synopsis
  4. #  Enumerates the parameters of one or more commands
  5. #.Notes
  6. #  With many thanks to Hal Rottenberg, Oisin Grehan and Shay Levy
  7. #  Version 0.80 - April 2008 - By Hal Rottenberg http://poshcode.org/186
  8. #  Version 0.81 - May 2008 - By Hal Rottenberg http://poshcode.org/255
  9. #  Version 0.90 - June 2008 - By Hal Rottenberg http://poshcode.org/445
  10. #  Version 0.91 - June 2008 - By Oisin Grehan http://poshcode.org/446
  11. #  Version 0.92 - April 2008 - By Hal Rottenberg http://poshcode.org/549
  12. #               - Added resolving aliases and avoided empty output
  13. #  Version 0.93 - Sept 24, 2009 - By Hal Rottenberg http://poshcode.org/1344
  14. #  Version 1.0  - Jan 19, 2010 - By Joel Bennett http://poshcode.org/1592
  15. #               - Merged Oisin and Hal's code with my own implementation
  16. #               - Added calculation of dynamic paramters
  17. #  Version 2.0  - July 22, 2010 - By Joel Bennett http://poshcode.org/get/2005
  18. #               - Now uses FormatData so the output is objects
  19. #               - Added calculation of shortest names to the aliases (idea from Shay Levy http://poshcode.org/1982, but with a correct implementation)
  20. #  Version 2.1  - July 22, 2010 - By Joel Bennett http://poshcode.org/2007
  21. #               - Fixed Help for SCRIPT file (script help must be separated from #Requires by an emtpy line)
  22. #               - Fleshed out and added dates to this version history after Bergle's criticism ;)
  23. #  Version 2.2  - July 29, 2010 - By Joel Bennett (This Version)
  24. #               - Fixed a major bug which caused Get-Parameters to delete all the parameters from the CommandInfo
  25. #  Version 2.3  - July 29, 2010 - By Joel Bennett (This Version)
  26. #               - Added a ToString ScriptMethod which allows queries like:
  27. #                 $parameters = Get-Parameter Get-Process; $parameters -match "Name"
  28. #  Version 2.4  - July 29, 2010 - By Joel Bennett (This Version)
  29. #               - CHANGED "Name" to CommandName
  30. #               - ADDED ParameterName parameter to allow filtering parameters
  31. #               - Fixed bug in 2.3 and 2.2 with dynamic parameters
  32. #
  33. #.Description
  34. #  Lists all the parameters of a command, by ParameterSet, including their aliases, type, etc.
  35. #
  36. #  By default, formats the output to tables grouped by command and parameter set
  37. #.Example
  38. #  Get-Command Select-Xml | Get-Parameter
  39. #.Example
  40. #  Get-Parameter Select-Xml
  41. #.Parameter CommandName
  42. #  The name of the command to get parameters for
  43. #.Parameter ParameterName
  44. #  Wilcard-enabled filter for parameter names
  45. #.Parameter ModuleName
  46. #  The name of the module which contains the command (this is for scoping)
  47. #.Parameter Force
  48. #  Forces including the CommonParameters in the output
  49. [CmdletBinding()]
  50. param (
  51.    [Parameter(Position=1,ValueFromPipelineByPropertyName=$true,Mandatory=$true)]
  52.    [Alias("Name")]
  53.    [string[]]$CommandName
  54. ,
  55.    [Parameter(Position=2,ValueFromPipelineByPropertyName=$true,Mandatory=$false)]
  56.    [string[]]$ParameterName="*"
  57. ,
  58.    [Parameter(ValueFromPipelineByPropertyName=$true,Mandatory=$false)]
  59.    $ModuleName
  60. ,
  61.    [switch]$Force
  62. )
  63.  
  64. Function global:Get-Parameter {
  65. #.Synopsis
  66. #  Enumerates the parameters of one or more commands
  67. #.Description
  68. #  Lists all the parameters of a command, by ParameterSet, including their aliases, type, etc.
  69. #
  70. #  By default, formats the output to tables grouped by command and parameter set
  71. #.Example
  72. #  Get-Command Select-Xml | Get-Parameter
  73. #.Example
  74. #  Get-Parameter Select-Xml
  75. #.Parameter CommandName
  76. #  The name of the command to get parameters for
  77. #.Parameter ParameterName
  78. #  Wilcard-enabled filter for parameter names
  79. #.Parameter ModuleName
  80. #  The name of the module which contains the command (this is for scoping)
  81. #.Parameter Force
  82. #  Forces including the CommonParameters in the output
  83. [CmdletBinding()]
  84. param (
  85.    [Parameter(Position=1,ValueFromPipelineByPropertyName=$true,Mandatory=$true)]
  86.    [string[]]$CommandName
  87. ,
  88.    [Parameter(Position=2,ValueFromPipelineByPropertyName=$true,Mandatory=$false)]
  89.    [string[]]$ParameterName="*"
  90. ,
  91.    [Parameter(ValueFromPipelineByPropertyName=$true,Mandatory=$false)]
  92.    $ModuleName
  93. ,
  94.    [switch]$Force
  95. )
  96. begin {
  97.    $PropertySet = @( "Name",
  98.                      @{n="Position";e={if($_.Position -lt 0){"Named"}else{$_.Position}}},
  99.                      "Aliases",
  100.                      @{n="Short";e={$_.Name}},
  101.                      @{n="Type";e={$_.ParameterType.Name}},
  102.                      @{n="ParameterSet";e={$paramset}},
  103.                      @{n="Command";e={$command}},
  104.                      @{n="Mandatory";e={$_.IsMandatory}},
  105.                      @{n="Provider";e={$_.DynamicProvider}},
  106.                      @{n="ValueFromPipeline";e={$_.ValueFromPipeline}},
  107.                      @{n="ValueFromPipelineByPropertyName";e={$_.ValueFromPipelineByPropertyName}}
  108.                   )
  109.    function Join-Object {
  110.    Param(
  111.       [Parameter(Position=0)]
  112.       $First
  113.    ,
  114.       [Parameter(ValueFromPipeline=$true,Position=1)]
  115.       $Second
  116.    )
  117.       begin {
  118.          [string[]] $p1 = $First | gm -type Properties | select -expand Name
  119.       }
  120.       process {
  121.          $Output = $First | Select $p1
  122.          foreach($p in $Second | gm -type Properties | Where { $p1 -notcontains $_.Name } | select -expand Name) {
  123.             Add-Member -in $Output -type NoteProperty -name $p -value $Second."$p"
  124.          }
  125.          $Output
  126.       }
  127.    }
  128. }
  129. process{
  130.    foreach($cmd in $CommandName) {
  131.       if($ModuleName)   { $cmd = "$ModuleName\$cmd" }
  132.       $commands = @(Get-Command $cmd)
  133.  
  134.       foreach($command in $commands) {
  135.          # resolve aliases (an alias can point to another alias)
  136.          while ($command.CommandType -eq "Alias") {
  137.             $command = @(Get-Command ($command.definition))[0]
  138.          }
  139.          if (-not $command) { continue }
  140.  
  141.          $Parameters = @{}
  142.  
  143.          foreach($provider in Get-PSProvider) {
  144.             $drive = "{0}\{1}::\" -f $provider.ModuleName, $provider.Name
  145.             Write-Verbose ("Get-Command $command -Args $drive | Select -Expand Parameters")
  146.            
  147.             [Array]$MoreParameters = (Get-Command $command -Args $drive).Parameters.Values
  148.             [Array]$Dynamic = $MoreParameters | Where { $_.IsDynamic }
  149.              
  150.             foreach($p in $MoreParameters | Where { !$Parameters.ContainsKey( $_.Name ) } ){ $Parameters.($p.Name) = $p }
  151.            
  152.             # Write-Verbose "Drive: $Drive | Parameters: $($Parameters.Count)"
  153.             if($dynamic) {
  154.                foreach($d in $dynamic) {
  155.                   if(Get-Member -input $Parameters.($d.Name) -Name DynamicProvider) {
  156.                      Write-Debug ("ADD:" + $d.Name + " " + $provider.Name)
  157.                      $Parameters.($d.Name).DynamicProvider += $provider.Name
  158.                   } else {
  159.                      Write-Debug ("CREATE:" + $d.Name + " " + $provider.Name)
  160.                      $Parameters.($d.Name) = $Parameters.($d.Name) | Add-Member NoteProperty DynamicProvider @($provider.Name) -Passthru
  161.                   }
  162.                }
  163.             }
  164.          }
  165.          
  166.          ## Calculate the shortest distinct parameter name -- do this BEFORE removing the common parameters or else.
  167.          foreach($p in $($Parameters.Keys))
  168.          {
  169.             $shortest="^"
  170.             foreach($char in [char[]]$p)
  171.             {            
  172.                $shortest += $char
  173.                $Matches = ($Parameters.Keys -match $Shortest).Count
  174.                Write-Debug "$($shortest.SubString(1)) $Matches"
  175.                if($Matches -eq 1)
  176.                {
  177.                   $Parameters.$p = $Parameters.$p | Add-Member NoteProperty Aliases ($Parameters.$p.Aliases + @($shortest.SubString(1).ToLower($PSUICulture))) -Force -Passthru
  178.                   break
  179.                }
  180.             }
  181.          }
  182.    
  183.          Write-Verbose "Parameters: $($Parameters.Count)`n $($Parameters | ft | out-string)"
  184.        
  185.          foreach ($paramset in @($command.ParameterSets | Select -Expand "Name")){
  186.             foreach($parameter in $Parameters.Keys | Sort) {
  187.                Write-Verbose "Parameter: $Parameter"
  188.                if(!$Force -and ($Parameters.$Parameter.aliases -match "vb|db|ea|wa|ev|wv|ov|ob|wi|cf")) { continue }
  189.                if($Parameters.$Parameter.ParameterSets.ContainsKey($paramset) -or $Parameters.$Parameter.ParameterSets.ContainsKey("__AllParameterSets")) {                  
  190.                   if($Parameters.$Parameter.ParameterSets.ContainsKey($paramset)) {
  191.                      $output = Join-Object $Parameters.$Parameter $Parameters.$Parameter.ParameterSets.$paramSet
  192.                   } else {
  193.                      $output = Join-Object $Parameters.$Parameter $Parameters.$Parameter.ParameterSets.__AllParameterSets
  194.                   }
  195.                  
  196.                   Write-Output $Output | Select-Object $PropertySet | ForEach {
  197.                      $null = $_.PSTypeNames.Insert(0,"System.Management.Automation.ParameterMetadata")
  198.                      $null = $_.PSTypeNames.Insert(0,"System.Management.Automation.ParameterMetadataEx")
  199.                      Write-Verbose "$(($_.PSTypeNames.GetEnumerator()) -join ", ")"
  200.                      $_
  201.                   } |
  202.                   Add-Member ScriptMethod ToString { $this.Name } -Force -Passthru  |
  203.                   Where-Object { $(foreach($pn in $ParameterName){ $_ -like $Pn}) -contains $true }
  204.                }
  205.             }
  206.          }
  207.       }
  208.    }
  209. }
  210. }
  211.  
  212.  
  213. # Since you can't update format data without a file that has a ps1xml ending, let's make one up...
  214. $tempFile = "$([IO.Path]::GetTempFileName()).ps1xml"
  215. Set-Content $tempFile @'
  216. <?xml version="1.0" encoding="utf-8" ?>
  217. <Configuration>
  218.    <Controls>
  219.        <Control>
  220.            <Name>ParameterGroupingFormat</Name>
  221.              <CustomControl>
  222.                  <CustomEntries>
  223.                      <CustomEntry>
  224.                          <CustomItem>
  225.                              <Frame>
  226.                                  <LeftIndent>4</LeftIndent>
  227.                                  <CustomItem>
  228.                                      <Text>Command: </Text>
  229.                                      <ExpressionBinding>
  230.                                          <ScriptBlock>"{0}/{1}" -f $(if($_.command.ModuleName){$_.command.ModuleName}else{$_.Command.CommandType.ToString()+":"}),$_.command.Name</ScriptBlock>
  231.                                      </ExpressionBinding>
  232.                                      <NewLine/>
  233.                                      <Text>Set:     </Text>
  234.                                      <ExpressionBinding>
  235.                                          <ScriptBlock>if($_.ParameterSet -eq "__AllParameterSets"){"Default"}else{$_.ParameterSet}</ScriptBlock>
  236.                                      </ExpressionBinding>
  237.                                      <NewLine/>
  238.                                  </CustomItem>
  239.                              </Frame>
  240.                          </CustomItem>
  241.                      </CustomEntry>
  242.                  </CustomEntries>
  243.            </CustomControl>
  244.        </Control>
  245.    </Controls>
  246.    <ViewDefinitions>
  247.        <View>
  248.            <Name>ParameterMetadataEx</Name>
  249.            <ViewSelectedBy>
  250.                <TypeName>System.Management.Automation.ParameterMetadataEx</TypeName>
  251.            </ViewSelectedBy>
  252.            <GroupBy>
  253.                <PropertyName>ParameterSet</PropertyName>
  254.                <CustomControlName>ParameterGroupingFormat</CustomControlName>  
  255.            </GroupBy>
  256.            <TableControl>
  257.                <TableHeaders>
  258.                    <TableColumnHeader>
  259.                        <Label>Name</Label>
  260.                        <Width>22</Width>
  261.                    </TableColumnHeader>
  262.                    <TableColumnHeader>
  263.                        <Label>Aliases</Label>
  264.                        <Width>12</Width>
  265.                    </TableColumnHeader>
  266.                    <TableColumnHeader>
  267.                        <Label>Position</Label>
  268.                        <Width>8</Width>
  269.                    </TableColumnHeader>
  270.                    <TableColumnHeader>
  271.                        <Label>Mandatory</Label>
  272.                        <Width>9</Width>
  273.                    </TableColumnHeader>
  274.                    <TableColumnHeader>
  275.                        <Label>Pipeline</Label>
  276.                        <Width>8</Width>
  277.                    </TableColumnHeader>
  278.                    <TableColumnHeader>
  279.                        <Label>ByName</Label>
  280.                        <Width>6</Width>
  281.                    </TableColumnHeader>
  282.                    <TableColumnHeader>
  283.                        <Label>Provider</Label>
  284.                        <Width>15</Width>
  285.                    </TableColumnHeader>
  286.                    <TableColumnHeader>
  287.                        <Label>Type</Label>
  288.                    </TableColumnHeader>
  289.                </TableHeaders>
  290.                <TableRowEntries>
  291.                    <TableRowEntry>
  292.                        <TableColumnItems>
  293.                            <TableColumnItem>
  294.                                <PropertyName>Name</PropertyName>
  295.                            </TableColumnItem>
  296.                            <TableColumnItem>
  297.                                <PropertyName>Aliases</PropertyName>
  298.                            </TableColumnItem>
  299.                            <TableColumnItem>
  300.                                <!--PropertyName>Position</PropertyName-->
  301.                                <ScriptBlock>if($_.Position -lt 0){"Named"}else{$_.Position}</ScriptBlock>
  302.                            </TableColumnItem>
  303.                            <TableColumnItem>
  304.                                <PropertyName>Mandatory</PropertyName>
  305.                            </TableColumnItem>
  306.                            <TableColumnItem>
  307.                                <PropertyName>ValueFromPipeline</PropertyName>
  308.                            </TableColumnItem>
  309.                            <TableColumnItem>
  310.                                <PropertyName>ValueFromPipelineByPropertyName</PropertyName>
  311.                            </TableColumnItem>
  312.                            <TableColumnItem>
  313.                                <!--PropertyName>Provider</PropertyName-->
  314.                                <ScriptBlock>if($_.Provider){$_.Provider}else{"All"}</ScriptBlock>
  315.                            </TableColumnItem>
  316.                            <TableColumnItem>
  317.                                <PropertyName>Type</PropertyName>
  318.                            </TableColumnItem>
  319.                        </TableColumnItems>
  320.                    </TableRowEntry>
  321.                 </TableRowEntries>
  322.            </TableControl>
  323.        </View>
  324.    </ViewDefinitions>
  325. </Configuration>
  326. '@
  327.  
  328. Update-FormatData -Append $tempFile
  329.  
  330.  
  331. # This is nested stuff, so that you can call the SCRIPT, and after it defines the global function, we will call that.
  332. Get-Parameter @PSBoundParameters

Submit a correction or amendment below (
click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.

Syntax highlighting:


Remember me