为什么PowerShell的`Get-ChildItem`命令将参数`d`解析为`Depth`?
鉴于它Get-ChildItem具有三个以字符开头的参数D......
? (gcm Get-ChildItem).Parameters.Values |? Name -like 'd*' | select name, aliases
Name Aliases
---- -------
Depth {}
Debug {db}
Directory {ad, d}
...并且该Directory参数具有显式别名ad和d,为什么Get-ChildItem -d解析为Get-ChildItem -Depth?
? Get-ChildItem -d
Get-ChildItem: Missing an argument for parameter 'Depth'. Specify a parameter of type 'System.UInt32' and try again.
回答
这是因为其他参数是根据您询问的路径在调用时添加的动态参数。
-Directory仅Path在 FileSystem 提供程序中时才有效-DnsName并且-DocumentEncryptionCert仅在证书提供者中有效
与-re存在相同,而-Recurse不是对-ReadOnly......
这也是与同-e是-Exclude代替-Eku或-ExpiriringInDays...
而且您会注意到,如果您运行Get-ChildItem -f并告诉您f不明确,那么它建议的唯一选项是-Filterand -Force, not-File或-FollowSymlinkFileSystem 提供程序独有的选项......
您可以通过以下方式查看Get-Parameter可以从 PowerShell 库中获取的所有内容Install-Script Get-Parameter
我最终找到了一种通过实验证明非动态参数总是首先被解析的方法,并且参数绑定器甚至从不查看动态参数,它可以在没有它们的情况下绑定任何东西。因此,参数选择器甚至不知道动态参数的名称或别名是什么,除非在非动态参数上找不到匹配项。所以这个d别名只会引起混乱,除非它是以这样的方式生成的,它也会出现在其他命令中......
尝试这个:
using namespace System.Management.Automation
function Test-Alias {
[CmdletBinding()]
param(
[switch]$Awful
)
dynamicparam {
$paramDictionary = [RuntimeDefinedParameterDictionary]::new()
$attribs = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
$attribs.Add([ParameterAttribute]@{ParameterSetName = "_AllParameterSets" })
$paramdictionary.Add("Automation", [RuntimeDefinedParameter]::new( "Automation", [switch], $attribs))
$attribs += [AliasAttribute]::new("A", "C")
$paramdictionary.Add("Architecture", [RuntimeDefinedParameter]::new( "Architecture", [switch], $attribs))
$paramdictionary
}
end {
$PSBoundParameters
}
}
如果你在你的控制台中运行它,你不仅可以看到它的Test-Alias -A用途,Awful而且它Test-Alias -C确实有效!A 别名从来没有机会,但这不是因为动态参数的别名被完全忽略,而是因为有一个以该字母开头的参数不是 dynamic。
现在试试这个:
Trace-Command -Name ParameterBinding { Test-Alias -A } -PSHost
并将其与您使用Test-Alias -C或时的输出进行比较Test-Alias -A -C...
您可以看到 Dynamic 参数仅在可以绑定的所有非动态参数之后才考虑。