通过


可视化参数绑定

参数绑定是 PowerShell 用于确定正在使用的具体参数集并用于将值关联(绑定到)命令参数的过程。 这些值可能来自命令行和管道。

参数绑定过程首先绑定命名自变量和位置命令行自变量。 绑定命令行自变量后,PowerShell 会尝试绑定任何管道输入。 可通过两种方式从管道绑定值。 接受管道输入的参数具有下面一个或两个特性:

  • ValueFromPipeline - 管道中的值根据其类型绑定到参数。 自变量的类型必须与参数的类型匹配。
  • ValueFromPipelineByPropertyName - 管道中的值根据其名称绑定到参数。 管道中的对象必须具有与参数的名称或其别名之一匹配的属性。 属性的类型必须匹配或可转换为参数的类型。

有关参数绑定的详细信息,请参阅 about_Parameter_Binding

使用 Trace-Command 可视化参数绑定

排查参数绑定问题可能很困难。 可以使用 Trace-Command cmdlet 可视化参数绑定过程。

请考虑以下场景。 你有一个目录,其中包含两个文本文件 - file1.txt[file2].txt

PS> Get-ChildItem

    Directory: D:\temp\test\binding

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           5/17/2024 12:59 PM              0 [file2].txt
-a---           5/17/2024 12:59 PM              0 file1.txt

你需要通过管道将文件名传递给 Remove-Item cmdlet 来删除文件。

PS> 'file1.txt', '[file2].txt' | Remove-Item
PS> Get-ChildItem

    Directory: D:\temp\test\binding

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---           5/17/2024 12:59 PM              0 [file2].txt

请注意,Remove-Item 仅删除了 file1.txt,而不是 [file2].txt。 文件名包括方括号,该括号被视为通配符表达式。 使用 Trace-Command,可以看到文件名绑定到 Remove-Item 的 Path 参数。

Trace-Command -PSHost -Name ParameterBinding -Expression {
    '[file2].txt' | Remove-Item
}

Trace-Command 的输出可能非常详细。 每行输出都以时间戳和跟踪提供程序信息为前缀。 对于此示例的输出,已删除前缀信息,使其更易于阅读。

BIND NAMED cmd line args [Remove-Item]
BIND POSITIONAL cmd line args [Remove-Item]
BIND cmd line args to DYNAMIC parameters.
    DYNAMIC parameter object: [Microsoft.PowerShell.Commands.FileSystemProviderRemoveItemDynamicParameters]
MANDATORY PARAMETER CHECK on cmdlet [Remove-Item]
CALLING BeginProcessing
BIND PIPELINE object to parameters: [Remove-Item]
    PIPELINE object TYPE = [System.String]
    RESTORING pipeline parameter's original values
    Parameter [Path] PIPELINE INPUT ValueFromPipeline NO COERCION
    BIND arg [[file2].txt] to parameter [Path]
        Binding collection parameter Path: argument type [String], parameter type [System.String[]],
            collection type Array, element type [System.String], no coerceElementType
        Creating array with element type [System.String] and 1 elements
        Argument type String is not IList, treating this as scalar
        Adding scalar element of type String to array position 0
        BIND arg [System.String[]] to param [Path] SUCCESSFUL
    Parameter [Credential] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
    Parameter [Credential] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
    Parameter [Credential] PIPELINE INPUT ValueFromPipelineByPropertyName WITH COERCION
    Parameter [Credential] PIPELINE INPUT ValueFromPipelineByPropertyName WITH COERCION
MANDATORY PARAMETER CHECK on cmdlet [Remove-Item]
CALLING ProcessRecord
CALLING EndProcessing

使用 Get-Help,可以看到 Remove-Item 的 Path 参数接受来自管道 ByValueByPropertyName 的字符串对象。 LiteralPath 接受管道 ByPropertyName 中的字符串对象。

PS> Get-Help Remove-Item -Parameter Path, LiteralPath

-Path <System.String[]>
    Specifies a path of the items being removed. Wildcard characters are permitted.

    Required?                    true
    Position?                    0
    Default value                None
    Accept pipeline input?       True (ByPropertyName, ByValue)
    Accept wildcard characters?  true


-LiteralPath <System.String[]>
    Specifies a path to one or more locations. The value of LiteralPath is used exactly as it's
    typed. No characters are interpreted as wildcards. If the path includes escape characters,
    enclose it in single quotation marks. Single quotation marks tell PowerShell not to interpret
    any characters as escape sequences.

    Required?                    true
    Position?                    named
    Default value                None
    Accept pipeline input?       True (ByPropertyName)
    Accept wildcard characters?  false

Trace-Command 的输出显示参数绑定是先绑定命令行参数,然后再绑定管道输入。 可以看到,Remove-Item 从管道接收字符串对象。 该字符串对象绑定到 Path 参数。

BIND PIPELINE object to parameters: [Remove-Item]
    PIPELINE object TYPE = [System.String]
    RESTORING pipeline parameter's original values
    Parameter [Path] PIPELINE INPUT ValueFromPipeline NO COERCION
    BIND arg [[file2].txt] to parameter [Path]
    ...
        BIND arg [System.String[]] to param [Path] SUCCESSFUL

由于 Path 参数接受通配符,方括号表示通配符表达式。 但是,该表达式与目录中的任何文件都不匹配。 需要使用 LiteralPath 参数来指定文件的确切路径。

Get-Command 显示,LiteralPath 参数接受管道 ByPropertyNameByValue 的输入。 而且,它有两个别名 - PSPathLP

PS> (Get-Command Remove-Item).Parameters.LiteralPath.Attributes |
>> Select-Object ValueFrom*, Alias* | Format-List

ValueFromPipeline               : False
ValueFromPipelineByPropertyName : True
ValueFromRemainingArguments     : False

AliasNames : {PSPath, LP}

在这下一个示例中,Get-Item 用于检索 FileInfo 对象。 该对象具有名为 PSPath 的属性。

PS> Get-Item *.txt | Select-Object PSPath

PSPath
------
Microsoft.PowerShell.Core\FileSystem::D:\temp\test\binding\[file2].txt

然后,FileInfo 对象传递给 Remove-Item 方法。

Trace-Command -PSHost -Name ParameterBinding -Expression {
    Get-Item *.txt | Remove-Item
}

对于此示例的输出,前缀信息已被删除并分隔,以显示这两个命令的参数绑定。

在此输出中,可以看到,Get-Item 将位置参数值 *.txt 绑定到 Path 参数。

BIND NAMED cmd line args [Get-Item]
BIND POSITIONAL cmd line args [Get-Item]
    BIND arg [*.txt] to parameter [Path]
        Binding collection parameter Path: argument type [String], parameter type [System.String[]],
            collection type Array, element type [System.String], no coerceElementType
        Creating array with element type [System.String] and 1 elements
        Argument type String is not IList, treating this as scalar
        Adding scalar element of type String to array position 0
        BIND arg [System.String[]] to param [Path] SUCCESSFUL
BIND cmd line args to DYNAMIC parameters.
    DYNAMIC parameter object: [Microsoft.PowerShell.Commands.FileSystemProviderGetItemDynamicParameters]
MANDATORY PARAMETER CHECK on cmdlet [Get-Item]

在参数绑定的跟踪输出中,可以看到 Remove-Item 从管道接收 FileInfo 对象。 由于 FileInfo 对象不是 String 对象,因此它不能绑定到 Path 参数。

FileInfo 对象的 PSPath 属性与 LiteralPath 参数的别名匹配。 PSPath 也是一个 String 对象,因此它可以绑定到没有类型强制的 LiteralPath 参数。

BIND NAMED cmd line args [Remove-Item]
BIND POSITIONAL cmd line args [Remove-Item]
BIND cmd line args to DYNAMIC parameters.
    DYNAMIC parameter object: [Microsoft.PowerShell.Commands.FileSystemProviderRemoveItemDynamicParameters]
MANDATORY PARAMETER CHECK on cmdlet [Remove-Item]
CALLING BeginProcessing
CALLING BeginProcessing
CALLING ProcessRecord
    BIND PIPELINE object to parameters: [Remove-Item]
        PIPELINE object TYPE = [System.IO.FileInfo]
        RESTORING pipeline parameter's original values
        Parameter [Path] PIPELINE INPUT ValueFromPipeline NO COERCION
        BIND arg [D:\temp\test\binding\[file2].txt] to parameter [Path]
            Binding collection parameter Path: argument type [FileInfo], parameter type [System.String[]],
                collection type Array, element type [System.String], no coerceElementType
            Creating array with element type [System.String] and 1 elements
            Argument type FileInfo is not IList, treating this as scalar
            BIND arg [D:\temp\test\binding\[file2].txt] to param [Path] SKIPPED
        Parameter [Credential] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
        Parameter [Path] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
        Parameter [Credential] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
        Parameter [LiteralPath] PIPELINE INPUT ValueFromPipelineByPropertyName NO COERCION
        BIND arg [Microsoft.PowerShell.Core\FileSystem::D:\temp\test\binding\[file2].txt] to parameter [LiteralPath]
            Binding collection parameter LiteralPath: argument type [String], parameter type [System.String[]],
                collection type Array, element type [System.String], no coerceElementType
            Creating array with element type [System.String] and 1 elements
            Argument type String is not IList, treating this as scalar
            Adding scalar element of type String to array position 0
            BIND arg [System.String[]] to param [LiteralPath] SUCCESSFUL
        Parameter [Credential] PIPELINE INPUT ValueFromPipelineByPropertyName WITH COERCION
    MANDATORY PARAMETER CHECK on cmdlet [Remove-Item]
    CALLING ProcessRecord
CALLING EndProcessing
CALLING EndProcessing