参数绑定是 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 参数接受来自管道 ByValue 或 ByPropertyName 的字符串对象。 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 参数接受管道 ByPropertyName 或 ByValue 的输入。 而且,它有两个别名 - PSPath 和 LP。
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