英文:
Inconsistent binding when piping DirectoryInfo objects
问题
I've often used a construct similar to this (using aliases for brevity):
gci -ad | %{$_ | gci}
which works fine. But when trying to help another user on this forum, I found that the following doesn't work:
gci -ad | %{$_.Parent | gci}
throws the following error for each iteration:
gci : Cannot find path 'C:\Users\keith\Documents\Documents' because it does not exist.
At line:1 char:25
+ gci -ad | %{$_.Parent | gci}
+ ~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\keith\Documents\Documents:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
even though:
gci -ad | %{$_.GetType() -eq $_.Parent.GetType()}
produces a screen full of True
.
I'm pretty sure it has something to do with parameter binding, but would like to understand the apparent inconsistency.
英文:
I've often used a construct similar to this (using aliases for brevity):
gci -ad | %{$_ | gci}
which works fine. But when trying to help another user on this forum, I found that the following doesn't work:
gci -ad | %{$_.Parent | gci}
throws the following error for each iteration:
gci : Cannot find path 'C:\Users\keith\Documents\Documents' because it does not exist.
At line:1 char:25
+ gci -ad | %{$_.Parent | gci}
+ ~~~
+ CategoryInfo : ObjectNotFound: (C:\Users\keith\Documents\Documents:Stri
ng) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemC
ommand
even though:
gci -ad | %{$_.GetType() -eq $_.Parent.GetType()}
produces a scrennfull of True
.
I'm pretty sure it has something to do with parameter binding, but would like to understand the apparent inconsistancy....
答案1
得分: 2
以下是您要翻译的内容:
"最容易了解发生了什么的方法是使用测试函数模拟绑定,但问题是,正如您可能知道的,在.NET Framework中,当将DirectoryInfo
实例强制转换为字符串时,结果将是其.Name
属性值,而不是.NET中的情况,其中强制转换会导致.FullName
属性。
由于调用.Parent
属性返回的对象没有ETS属性.PSPath
,因此输入对象将绑定到Path
参数并强制转换为字符串。
假设您同时拥有PowerShell的两个版本,您可以尝试以下内容以查看差异:
function Test-Binding {
[CmdletBinding(DefaultParameterSetName='Items')]
param(
[Parameter(ParameterSetName='Items', Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[string[]]
${Path},
[Parameter(ParameterSetName='LiteralItems', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
[Alias('PSPath')]
[string[]]
${LiteralPath}
)
process {
$PSBoundParameters
$PSBoundParameters.Clear()
}
}
(Get-Item .), (Get-Item .).Parent | Test-Binding
英文:
Easiest way to see what's happening is to emulate the binding with a test function, but the issue is, as you might know in .NET Framework when a DirectoryInfo
instance is coerced into a string the result will be it's .Name
property value as opposed to .NET where the coercion results in the .FullName
property.
Since the object returned by calling the .Parent
property does not have the ETS Property .PSPath
, the input object will be bound the the Path
Parameter and coerced to a string.
Assuming you have both versions of PowerShell, you can try the following to see the difference:
function Test-Binding {
[CmdletBinding(DefaultParameterSetName='Items')]
param(
[Parameter(ParameterSetName='Items', Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
[string[]]
${Path},
[Parameter(ParameterSetName='LiteralItems', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
[Alias('PSPath')]
[string[]]
${LiteralPath}
)
process {
$PSBoundParameters
$PSBoundParameters.Clear()
}
}
(Get-Item .), (Get-Item .).Parent | Test-Binding
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论