How does powershell resolve command names?

2020-03-02 07:58发布

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.

标签: powershell
3条回答
够拽才男人
2楼-- · 2020-03-02 08:04

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.

查看更多
劳资没心,怎么记你
3楼-- · 2020-03-02 08:18

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.'
查看更多
家丑人穷心不美
4楼-- · 2020-03-02 08:24

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                                                                                       
查看更多
登录 后发表回答