about_Command_Precedence

简短说明

介绍 PowerShell 如何确定要运行哪个命令。

长说明

命令优先级描述当会话包含多个具有相同名称的命令时,PowerShell 如何确定要运行的命令。 会话中的命令可以隐藏或替换为具有相同名称的命令。 本文介绍如何运行隐藏的命令以及如何避免命令名称冲突。

命令优先级

当 PowerShell 会话包含多个具有相同名称的命令时,PowerShell 将使用以下规则确定要运行的命令。

如果指定命令的路径,PowerShell 将在路径指定的位置运行该命令。

例如,以下命令在 C:\TechDocs 目录中运行 FindDocs.ps1 脚本:

C:\TechDocs\FindDocs.ps1

可以使用其完整路径运行任何可执行命令。 作为安全功能,PowerShell 不会运行可执行命令,包括 PowerShell 脚本和本机命令,除非命令位于 $env:Path 环境变量中列出的路径中。

若要运行当前目录中的可执行文件,请指定完整路径或使用相对路径 .\ 表示当前目录。

例如,若要在当前目录中运行 FindDocs.ps1 文件,请键入:

.\FindDocs.ps1

如果未指定路径,PowerShell 会在运行命令时使用以下优先顺序。

  1. 别名
  2. 函数
  3. Cmdlet(请参阅 Cmdlet 名称解析
  4. 外部可执行文件(包括 PowerShell 脚本文件)

因此,如果键入 help,PowerShell 会首先查找名为 help 的别名,然后查找名为 Help 的函数,最后查找名为 Help 的 cmdlet。 它运行找到的第一个 help 项。

例如,如果会话包含名称都为 Get-Map 的 cmdlet 和函数,则键入 Get-Map 时,PowerShell 将运行该函数。

注意

这仅适用于加载的命令。 如果对于未加载到当前会话中的模块中名为 Invoke-Build 的函数存在 build 可执行文件和别名 build,则 PowerShell 将运行 build 可执行文件。 如果找到外部可执行文件,则它不会自动加载模块。 仅当未找到任何外部可执行文件时,才会调用具有给定名称的别名、函数或 cmdlet。

解析具有相同名称的项目

由于这些规则,可以使用同名项目替换或隐藏项目。

如果你仍然可以访问原始项,例如通过使用模块名称限定项目名称,则项目将被隐藏屏蔽

例如,如果导入的函数与会话中的 cmdlet 同名,则 cmdlet 会被隐藏,但不替换。 可以通过指定 cmdlet 的模块限定名称来运行该 cmdlet。

当项目被替换覆盖时,你无法再访问原始项目。

例如,如果导入与会话中的变量同名的变量,则会替换原始变量。 不能使用模块名称限定变量。

如果在命令行创建函数,然后导入具有相同名称的函数,则将替换原始函数。

查找隐藏的命令

Get-Command cmdlet 的 All 参数将获取具有指定名称的所有命令,即使它们已被隐藏或替换。 从 PowerShell 3.0 开始,默认情况下 Get-Command 仅获取键入命令名称时运行的命令。

在以下示例中,会话包括 Get-Date 函数和 Get-Date cmdlet。 可以使用 Get-Command 来确定首先选择哪个命令。

Get-Command Get-Date
CommandType     Name                      ModuleName
-----------     ----                      ----------
Function        Get-Date

使用 All 参数列出可用的 Get-Date 命令。

Get-Command Get-Date -All
CommandType     Name                 Version    Source
-----------     ----                 -------    ------
Function        Get-Date
Cmdlet          Get-Date             7.0.0.0    Microsoft.PowerShell.Utility
Get-Command where -All
CommandType Name                     Version      Source
----------- ----                     -------      ------
Alias       where -> Where-Object
Application where.exe                10.0.22621.1 C:\Windows\system32\where.exe

可以通过包括将该命令与可能具有相同名称的其他命令区分开的限定信息来运行特定命令。 对于 cmdlet,可以使用模块限定的名称。 对于可执行文件,可以包含文件扩展名。 例如,若要运行 where 的可执行版本,请使用 where.exe

使用模块限定名称

使用 cmdlet 的模块限定名称,可以运行同名项目隐藏的命令。 例如,可以通过将其模块名称限定为 Microsoft.PowerShell.Utility 或其路径来运行 Get-Date cmdlet。 使用模块限定名称时,可以根据值 $PSModuleAutoLoadingPreference自动将模块导入会话中。

注意

不能使用模块名称来限定变量或别名。

使用模块限定的名称可确保运行要运行的命令。 这是编写要分发的脚本时调用 cmdlet 的建议方法。

以下示例演示如何通过包括命令的模块名称来限定命令。

重要

模块限定使用反斜杠字符 (\) 将模块名称与命令名称分开,而不考虑平台。

New-Alias -Name "Get-Date" -Value "Get-ChildItem"
Microsoft.PowerShell.Utility\Get-Date
Tuesday, May 16, 2023 1:32:51 PM

若要从 MapFunctions 模块运行 New-Map 命令,请使用其模块限定名称:

MapFunctions\New-Map

若要查找从中导入命令的模块,请使用命令的 ModuleName 属性。

(Get-Command <command-name>).ModuleName

例如,若要查找 Get-Date cmdlet 的源,请键入:

(Get-Command Get-Date).ModuleName
Microsoft.PowerShell.Utility

如果要使用模块的路径限定命令的名称,则必须在命令名称之前使用正斜杠(/)作为路径分隔符和反斜杠字符(\)。 使用以下示例运行 Get-Date cmdlet:

//localhost/c$/Progra~1/PowerShell/7-preview/Modules/Microsoft.PowerShell.Utility\Get-Date

该路径可以是完整路径,也可以是相对于当前位置的路径。 在 Windows 上,无法使用驱动器限定的路径。 必须使用 UNC 路径,如前面的示例所示,或相对于当前驱动器的路径。 以下示例假定当前位置位于驱动器中 C:

/Progra~1/PowerShell/7-preview/Modules/Microsoft.PowerShell.Utility\Get-Date

使用调用运算符

还可以使用调用运算符(&)通过将调用与 Get-ChildItem(别名为dirGet-CommandGet-Module 的调用结合使用来运行隐藏的命令。

调用运算符在子范围中执行字符串和脚本块。 有关详细信息,请参阅 about_Operators

例如,使用以下命令运行名为 Map 的函数,该函数由名为 Map 的别名隐藏。

& (Get-Command -Name Map -CommandType Function)

& (dir Function:\map)

还可以将隐藏的命令保存在变量中,以便更轻松地运行。

例如,以下命令将 Map 函数保存在 $myMap 变量中,然后使用 Call 运算符运行它。

$myMap = (Get-Command -Name map -CommandType function)
& ($myMap)

替换的项目

替换的项目是指无法再访问的项目。 可以通过从模块中导入同名项目来替换项目。

例如,如果在会话中键入 Get-Map 函数,并且导入名为 Get-Map 的函数,它将替换原始函数。 无法在当前会话中检索它。

变量和别名无法隐藏,因为无法使用调用运算符或限定的名称来运行它们。 从模块导入变量和别名时,它们会将会话中的变量替换为相同名称。

Cmdlet 名称解析

如果不使用 cmdlet 的限定名称,PowerShell 将检查该 cmdlet 是否已加载到当前会话中。 如果加载了多个包含相同 cmdlet 名称的模块,PowerShell 将使用第一个模块中按字母顺序找到的 cmdlet。

如果未加载 cmdlet,PowerShell 将搜索已安装的模块,并自动加载包含该 cmdlet 并运行该 cmdlet 的第一个模块。 PowerShell 在 $env:PSModulePath 环境变量中定义的每个路径中搜索模块。 路径按变量中列出的顺序进行搜索。 在每个路径中,模块按字母顺序搜索。 PowerShell 使用它找到的第一个匹配项中的 cmdlet。

避免名称冲突

管理命令名称冲突的最佳方式是防止冲突。 命名命令时,请使用唯一名称。 例如,将缩写或公司名称首字母缩略词添加到命令中的名词。

从 PowerShell 模块或其他会话导入命令时,可以使用 Import-ModuleImport-PSSession cmdlet 的 Prefix 参数将前缀添加到命令名称中的名词。

例如,以下命令可避免与导入 DateFunctions 模块时 PowerShell 附带的 Get-DateSet-Date cmdlet 发生任何冲突。

Import-Module -Name DateFunctions -Prefix ZZ

运行外部可执行文件

在 Windows 上。 PowerShell 将 $env:PATHEXT 环境变量中列出的文件扩展名视为可执行文件。 不是 Windows 可执行文件的文件将交给 Windows 进行处理。 Windows 查找文件关联,并执行扩展的默认 Windows Shell 谓词。 若要使 Windows 支持按文件扩展名执行,必须向系统注册关联。

可以使用 CMD 命令行界面的 ftypeassoc 命令为文件扩展名注册可执行文件引擎。 PowerShell 没有用于注册文件处理程序的直接方法。 有关详细信息,请参阅 ftype 命令的文档。

若要使 PowerShell 在当前会话中将文件扩展名视为可执行文件,必须将该扩展添加到 $env:PATHEXT 环境变量。

另请参阅