【问题标题】:How can I list all overloaded cmdlets defined in PowerShell?如何列出 PowerShell 中定义的所有重载 cmdlet?
【发布时间】:2021-11-11 16:23:41
【问题描述】:

背景:我们的一个团队有一个名为 Expand-Archive 的 Chocolatey 包。但是,我安装了 pscx 模块,提供了一个 Expand-Archive cmdlet,其参数签名与内置 cmdlet 不同,并导致此软件包安装失败。解决方案是在这种重载的情况下使用模块限定名称。最终能够查看online documentation 以获取模块名称的价值。

最初,我尝试使用以下方式获取模块:

Get-Command Expand-Archive -All

但这仅列出了在 pscx 模块中找到的 cmdlet。似乎Get-Command -All 不会从尚未加载的可用模块返回命令。这对于无法自动加载但不是像Microsoft.PowerShell.Archive 这样的内置模块有点意义,这令人担忧,因为它使我无法在不先加载模块的情况下审核会话中的可用命令。

一旦我使用以下方法之一加载模块:

Microsoft.PowerShell.Archive\Expand-Archive
Import-Module Microsoft.PowerShell.Archive

Get-Command Expand-Archive -All 确实以解析顺序显示了两个定义,以及它们所属的模块。虽然这是有问题的,因为它抑制了我审核系统上可用命令的能力,在运行 Get-Command 之前无法盲目导入所有可用模块(这本身就是一个有问题的解决方案)。


问题:我怎样才能告诉Get-Command实际上检索会话可用的所有可解析命令,或通过其他方式获取此信息?由于模块是根据其功能之一的第一次使用自动导入的(something 知道该命令在未加载的模块中进行导入),我希望Get-Command 应该 能够支持这个。

【问题讨论】:

  • Get-Command Expand-Archive -Module Microsoft.PowerShell.Archive 不起作用吗?
  • 当然,如果我提前知道模块的名称。在这种情况下,我试图找到命令所在的模块。

标签: powershell


【解决方案1】:

可用模块[1]中查找所有Export-Archive命令(相对于那些当前加载(导入)) :

Get-Module -ListAvailable |
  ForEach-Object { 
    if ($cmd = $_.ExportedCommands['Expand-Archive']) { $cmd }
  }

注意:Get-Module 输出的[System.Management.Automation.PSModuleInfo] 实例还具有特定于命令类型的.ExportedAliases.ExportedFunctions.ExportedCmdlets 属性,以及.ExportedVariables

注意:

  • 如果您安装了包含此类命令的模块的多个版本,则每个版本的命令将单独列出。

  • 输出不会告诉您哪个Export-Archive 命令是有效 的,即如果您将Export-Archive 作为命令提交,哪个将实际执行;要找到有效的,请使用Get-Command Export-Archive


至于你尝试了什么

Get-Command 原则上默认包含来自可用 模块的命令,但默认情况下仅显示该名称的有效 命令。

-All 开关 旨在以给定名称显示所有可用命令,即使是那些被有效命令隐藏的命令。

正如您所观察到的,-All 的使用意外地将源自模块的命令的候选池限制为来自当前加载的模块的命令,最多不超过PowerShell 核心 7.2.0-preview.9。

可以说,这是一个错误,已在GitHub issue #16116

中报告

可选Get-Command信息:

Get-Command 的行为没有名称 (-Name) 参数 - 无论有无 -All - 有点晦涩(尽管大部分都有记录) :

  • 除非您传递 -Type(-CommandType) 参数来显式控制要报告的命令类型,否则只会报告以下命令类型:AliasFunctionFilter、@987654347 @,其中特别排除了ExternalScript*.ps1 脚本文件)和Application(外部程序)。

    • 注意:-Type 接受 多个 值,因此要查找所有外部脚本和程序,例如,传递 -Type ExternalScript, Application
  • 要报告所有命令类型,请使用-Type All

  • 奇怪的是,不指定 -Name 参数似乎应用了 -All 开关,即阴影命令总是包含在内。

相比之下,如果指定了-Name 参数,则考虑所有命令类型,以及是否-All指定的确实有所作为。

  • 因此,Get-Command * 实际上与Get-Command -Type All 相同

[1] 可通过$env:PSModulePath 中列出的目录发现的,即通过module auto-loading

【讨论】:

  • 添加,Get-Command -All 不显示外部命令。您必须指定Get-Command -Type Application-All 的 cmdlet 文档中也没有提到此限制,但如果您给它一个外部命令名称,它将显示 PATH 上的所有匹配命令。
  • 谢谢,@BendertheGreatest - 我已将此信息添加到答案中,并且在此过程中我发现了一些其他内容 - 请参阅我的更新。简而言之:这不是关于 -All,而是关于是否传递了 -Name 参数,并且文档在这一点上并不是特别清楚。
  • @BendertheGreatest,文档所说的是“默认情况下,Get-Command 获取所有 cmdlet、函数和别名。”,但他们没有提到所有类型 都是 i> 一旦您使用 -Name 参数,就包含在内。 -All 与此区别无关。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-19
  • 2019-10-17
  • 2013-06-17
  • 2013-04-26
  • 1970-01-01
  • 2019-10-29
  • 2020-02-27
相关资源
最近更新 更多