Powershell: Suggestion: make it easier to discover which cmdlet parameters accept pipeline input, via the syntax diagram

Created on 28 Jun 2017  Â·  10Comments  Â·  Source: PowerShell/PowerShell

Related: #4715 and #4626.

Currently, it is not easy to discover which of a given cmdlet's / advanced function's parameters accept pipeline input and how (by value and/or by property name):

Using the example of Rename-Item:

  • You can use Get-Help Rename-Item -Full and then browse the entire topic for Accept pipeline input? lines

  • You can use a nontrivial command such as the following:
    Get-Help Rename-Item -Parameter * | ? pipelineInput -like 'true*' | Select-Object Name, Type, pipelineInput

The above yields:

name        type                       pipelineInput                 
----        ----                       -------------                 
Credential  @{name=PSCredential; uri=} true (ByPropertyName)         
LiteralPath @{name=String; uri=}       true (ByPropertyName)         
NewName     @{name=String; uri=}       true (ByPropertyName)         
Path        @{name=String; uri=}       true (ByValue, ByPropertyName)

Neither option is convenient.

Perhaps the syntax diagrams could be enhanced with symbols that reflect pipeline-binding behavior?

Something along the lines of (these are mere examples; the idea is to be concise):

  • | ... by value (only)
  • ⌠ ... by property name (only)
  • |⌠ ... by both value and property name

Applied to the Rename-Item example, with the symbols placed inside (...) after the parameter (for example):

Rename-Item [-Path(|⌠)] <String> [-NewName] <String> [-Credential(⌠) <PSCredential>] [-Force] [-PassThru] [-Confirm] [-WhatIf] [-UseTransaction <SwitchParameter>] 
    [<CommonParameters>]

Rename-Item [-NewName(⌠)] <String> [-Credential(⌠) <PSCredential>] [-Force] [-PassThru] -LiteralPath(⌠) <String> [-Confirm] [-WhatIf] [-UseTransaction <SwitchParameter>] 
    [<CommonParameters>]

Note: A crucial piece missing from the above is that parameters have _aliases_ and that binding by property name often happens via those aliases; e.g., Select-String's -LiteralPath has an alias of PSPath, and when you pipe Get-ChildItem output to Select-String, the objects bind by .PSPath, not .LiteralPath.

Written as of PowerShell Core v6.0.0-beta.3.

Issue-Enhancement WG-Interactive-HelpSystem

Most helpful comment

This is somewhat orthogonal to the Get-Command -Syntax request but a number of us PS users, rely on a command called Get-Parameter to get this info. It comes with the PSCX module. Here's the output from this command for Rename-Item:

PS C:\> Get-Parameter Rename-Item

    Command: Microsoft.PowerShell.Management/Rename-Item
    Set:    ByPath *


Name                   Aliases      Position Mandatory Pipeline ByName Provider        Type
----                   -------      -------- --------- -------- ------ --------        ----
Confirm                {cf}         Named    False     False    False  All             SwitchParameter
Credential             {Cr*}        Named    False     False    True   All             PSCredential
Force                  {F*}         Named    False     False    False  All             SwitchParameter
NewName                {N*}         1        True      False    True   All             String
PassThru               {Pas*}       Named    False     False    False  All             SwitchParameter
Path                   {Pat*}       0        True      True     True   All             String
UseTransaction         {usetx}      Named    False     False    False  All             SwitchParameter
WhatIf                 {wi}         Named    False     False    False  All             SwitchParameter


    Command: Microsoft.PowerShell.Management/Rename-Item
    Set:    ByLiteralPath


Name                   Aliases      Position Mandatory Pipeline ByName Provider        Type
----                   -------      -------- --------- -------- ------ --------        ----
Confirm                {cf}         Named    False     False    False  All             SwitchParameter
Credential             {Cr*}        Named    False     False    True   All             PSCredential
Force                  {F*}         Named    False     False    False  All             SwitchParameter
LiteralPath            {PSPath, L*} Named    True      False    True   All             String
NewName                {N*}         1        True      False    True   All             String
PassThru               {Pas*}       Named    False     False    False  All             SwitchParameter
UseTransaction         {usetx}      Named    False     False    False  All             SwitchParameter
WhatIf                 {wi}         Named    False     False    False  All             SwitchParameter

Personally, I find this far easier to parse than the output of Get-Command -Syntax.

All 10 comments

I like the intent, not sure if I like the proposed syntax, but don't have an alternative off the top of my head

@SteveL-MSFT: Glad to hear it; I'm not too thrilled with the specific syntax myself, but I wanted to get the conversation started.

This is somewhat orthogonal to the Get-Command -Syntax request but a number of us PS users, rely on a command called Get-Parameter to get this info. It comes with the PSCX module. Here's the output from this command for Rename-Item:

PS C:\> Get-Parameter Rename-Item

    Command: Microsoft.PowerShell.Management/Rename-Item
    Set:    ByPath *


Name                   Aliases      Position Mandatory Pipeline ByName Provider        Type
----                   -------      -------- --------- -------- ------ --------        ----
Confirm                {cf}         Named    False     False    False  All             SwitchParameter
Credential             {Cr*}        Named    False     False    True   All             PSCredential
Force                  {F*}         Named    False     False    False  All             SwitchParameter
NewName                {N*}         1        True      False    True   All             String
PassThru               {Pas*}       Named    False     False    False  All             SwitchParameter
Path                   {Pat*}       0        True      True     True   All             String
UseTransaction         {usetx}      Named    False     False    False  All             SwitchParameter
WhatIf                 {wi}         Named    False     False    False  All             SwitchParameter


    Command: Microsoft.PowerShell.Management/Rename-Item
    Set:    ByLiteralPath


Name                   Aliases      Position Mandatory Pipeline ByName Provider        Type
----                   -------      -------- --------- -------- ------ --------        ----
Confirm                {cf}         Named    False     False    False  All             SwitchParameter
Credential             {Cr*}        Named    False     False    True   All             PSCredential
Force                  {F*}         Named    False     False    False  All             SwitchParameter
LiteralPath            {PSPath, L*} Named    True      False    True   All             String
NewName                {N*}         1        True      False    True   All             String
PassThru               {Pas*}       Named    False     False    False  All             SwitchParameter
UseTransaction         {usetx}      Named    False     False    False  All             SwitchParameter
WhatIf                 {wi}         Named    False     False    False  All             SwitchParameter

Personally, I find this far easier to parse than the output of Get-Command -Syntax.

@rkeithhill:

That's indeed a very nice representation, and perhaps integrating it via a different parameter, such as -ExtendedSyntax, is the solution (as opposed to cramming more information into the existing diagrams - though the two aren't mutually exclusive).

Incidentally, shouldn't Get-Help have a -Syntax parameter too? I was looking for it, not remembering that it exists for Get-Command only.

(As an aside: I can install the PSCX module on macOS, but it won't load (Could not load file or assembly 'Pscx.Core, Version=3.2.6024.39574, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.)).

PSCX has not been ported to .NET Core yet. It's on the backlog which just got a bit shorter with the Unicode esc seq PR going through. :-) I've also been waiting on .NET 2.0 to stabilize along with the required PS SDK for portable module development. I got a bit burned by hopping on ASP.NET Core way too soon (alpha days) and almost every new build broke my code.

Thanks for letting me know; allow me to continue the tangent: on Windows, I get a warning about howExpand-Archive,Get-Hash,prompt,Format-Hex,Get-Help,Get-Uptime would be shadowed - any plans to not shadow built-in cmdlets, or is there a way to load only those commands that don't shadow built-in ones?

Yes. This has been a continual issue (and a good one to have) with PSCX because we've introduced commands that over time have made their way into PowerShell (yay!).

As for loading module specific commands you can always module-prefix a command e.g. Microsoft.PowerShell.Archive\Expand-Archive.

Prefixing the command doesn't help if another module uses it and didn't prefix it themselves. You could use Import-Module -Prefix "CX" -Name PSCX to explicitly load PSCX with a custom prefix, though that would not be good for code re-use.

What I do is modify the PSD1 file in the module directory to comment it out from CmdletsToExport. However, it would be lost in an upgrade and need to be redone if that command is still there.

I should have more correctly stated that the example was using a module qualified name which is different from (user and module specified) prefixing. Module qualified names should always work because PowerShell will not let you load two different modules with the same name. Regardless, this thread is straying pretty far from the original issue.

To get back on track: I realized that just marking the parameters by their declared names may not be enough, given that binding often happens via _aliases_, so a more verbose presentation that includes aliases - such as the PSCX Get-Parameter cmdlet's - is definitely (also) needed.

Was this page helpful?
0 / 5 - 0 ratings