Reputation: 29538
I'm trying to figure out how powershell resolves names, but I can't seem to find any information.
Here is the scenario:
There exists an executable:
c:\stuff\log.exe
The path is set so $env:path = 'c:\stuff\'
I have a module loaded that includes a function name "log" and a binary cmdlet aliased as 'log'.
When I type "log" at the command line, how does PowerShell decide whether to execute c:\stuff\log.exe or the function name log, or the cmdlet alieased as log?
From experimentation it seems the resolution order is: Cmdlet Function executable on the path
But I can't find anything that documents this.
Upvotes: 11
Views: 2489
Reputation: 439307
To complement the great existing answers:
A simple, pragmatic way of determining what a given command name will execute and if there are other, shadowed commands with the same name:
Get-Command -All <commandName>
All commands with the given name will be listed in descending order of precedence, i.e., the effective command will be listed first.
For instance, Windows PowerShell has a built-in sc
alias for the Set-Content
cmdlet, which shadows the native sc.exe
(service-control) program (unless you invoke it as sc.exe
):
PS> Get-Command -All sc
CommandType Name Version Source
----------- ---- ------- ------
Alias sc -> Set-Content
Application sc.exe 10.0.17... C:\WINDOWS\system32\sc.exe
Upvotes: 4
Reputation: 95712
If you want to find out the order Powershell looks for a command try using the trace-command
cmdlet. For example:
PS C:\scripts> trace-command -name CommandDiscovery -command ls -PSHost
DEBUG: CommandDiscovery Information: 0 : Looking up command: ls
DEBUG: CommandDiscovery Information: 0 : Alias found: ls Get-ChildItem
DEBUG: CommandDiscovery Information: 0 : Cmdlet found: Get-ChildItem Microsoft.PowerShell.Commands.GetChildItemCommand
Directory: C:\scripts
Mode LastWriteTime Length Name
...
is nice and short, but:
PS> trace-command -name CommandDiscovery -command log -PSHost
on my system produces more than 1,000 lines of output as it searches for a non-existent log command.
The order seems to be basically expand aliases then find functions, cmdlets then search your path for the command, then do it all again with get-
prepended.
The language reference is fairly terse on this, but it does say:
3.8 Name lookup It is possible to have commands of different kinds all having the same name. The order in which name lookup is performed in such a case is alias, function, cmdlet, and external command.
If it mentions that when commands aren't found it tries again with 'get-' prepended I haven't found that bit.
Upvotes: 9
Reputation: 24343
From help about_Command_Precedence
:
If you do not specify a path, Windows PowerShell uses the following
precedence order when it runs commands:
1. Alias
2. Function
3. Cmdlet
4. Native Windows commands
Also,
When the session contains items of the same type that have the same
name, such as two cmdlets with the same name, Windows PowerShell
runs the item that was added to the session most recently.
Calling commands with the same name
about_Command_Precedence
also goes into detail about how to explicitly call commands with the same name.
Here are some ways to call a log
command from different sources.
# Add '.exe' for executables
log.exe 'This is my log message.'
# Specify the module name
MyModule\log 'This is my log message.'
# Specify alias vs function
&(gi alias:\log) 'This is my log message.'
&(gi function:\log) 'This is my log message.'
Upvotes: 14