Why does PowerShell's `Get-ChildItem` command resolve the parameter `d` to `Depth`?
It's because the other parameters are dynamic parameters added at invocation, based on the path you're asking about.
-Directory
is only valid when thePath
is in the FileSystem provider-DnsName
and-DocumentEncryptionCert
are only valid in the Certificate provider
It's the same with -re
being -Recurse
instead of being ambiguous with -ReadOnly
...
It's also the same with -e
being -Exclude
instead of -Eku
or -ExpiriringInDays
...
And you'll notice that if you run Get-ChildItem -f
and it tells you f
is ambiguous, the only options that it suggests are -Filter
and -Force
, not -File
or -FollowSymlink
which are exclusive to the FileSystem provider...
You can see all of that using Get-Parameter
which you can get from the PowerShell gallery by Install-Script Get-Parameter
I eventually found a way to show by experimentation that the non-dynamic parameters will always get resolved first, and the parameter binder never even looks at the dynamic parameters for anything it can bind without them. Therefore, the parameter selector doesn't even know what the names or aliases of the dynamic parameters are unless it can't find a match on the non-dynamic parameters. So that d
alias is just causing confusion, unless it's being generated in such a way that it also shows up on other commands...
Try this:
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
}
}
If you run that in your console, you'll not only be able to see that Test-Alias -A
uses Awful
but also that Test-Alias -C
does work! The A alias never had a chance, but it's not because aliases on dynamic parameters are ignored completely, it's because there was a parameter that started with that letter which was not dynamic.
Now try this:
Trace-Command -Name ParameterBinding { Test-Alias -A } -PSHost
And compare that to the output when you use Test-Alias -C
or Test-Alias -A -C
...
You can see that the Dynamic parameters are only considered after everything non-dynamic that can be bound has been.