首页 > 解决方案 > 如何在 Powershell 中列出所有已安装、可运行的 cmdlet?

问题描述

我想在 powershell 中列出所有已安装、可运行的 cmdlet 和函数,但Get-Command列出了以某种方式“存在”但未加载且不可运行的 cmdlet。

例如,Get-Command列出New-IseSnippet

PS W:\> get-command "*-*" -CommandType Function,Cmdlet | where name -like "New-IseSnippet" | select name,module,path

Name           Module path
----           ------ ----
New-IseSnippet ISE

所以看起来我们有一个New-IseSnippet命令——让我们检查一下:

PS W:\> get-command New-IseSnippet
get-command : The term 'New-IseSnippet' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that 
the path is correct and try again.
At line:1 char:1
+ get-command New-IseSnippet
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (New-IseSnippet:String) [Get-Command], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException,Microsoft.PowerShell.Commands.GetCommandCommand

不,我们可以运行它吗?:

PS W:\> New-IseSnippet
New-IseSnippet : The 'New-IseSnippet' command was found in the module 'ISE', but the module could not be loaded. For more information, run 'Import-Module ISE'.
At line:1 char:1
+ New-IseSnippet
+ ~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (New-IseSnippet:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CouldNotAutoloadMatchingModule

没有。

我们如何只获得已安装的、可运行的命令?

标签: powershell

解决方案


至于这个根查询......

我想在 powershell 中列出所有已安装、可运行的 cmdlet 和函数

...在我的个人图书馆中,这是我很久以前创建/汇总的片段的一部分,并根据需要进行了更新,正是针对这种用例。我的片段中还有更多内容,但这应该可以让您根据您的帖子获得您所追求的。这是我在 ISE / VSCode 中的代码片段库,我可以根据需要随时使用CTRL+J并在 ISE 中选择它,然后在 VSCode 中输入 Help 并选择它。

# Get parameters, examples, full and Online help for a cmdlet or function

# Get a list of all Modules
Get-Module -ListAvailable | 
Out-GridView -PassThru -Title 'Available modules'

# Get a list of all functions
Get-Command -CommandType Function | 
Out-GridView -PassThru -Title 'Available functions'

# Get a list of all commandlets
Get-Command -CommandType Cmdlet | 
Out-GridView -PassThru -Title 'Available cmdlets'

# Get a list of all functions for the specified name
Get-Command -Name '*ADGroup*' -CommandType Function | 
Out-GridView -PassThru -Title 'Available named functions'

# Get a list of all commandlets for the specified name
Get-Command -Name '*ADGroup**'  -CommandType Cmdlet | 
Out-GridView -PassThru -Title 'Available named cmdlet'

# get function / cmdlet details
Get-Command -Name Get-ADUser -Syntax
(Get-Command -Name Get-ADUser).Parameters.Keys
Get-help -Name Get-ADUser -Full
Get-help -Name Get-ADUser -Online
Get-help -Name Get-ADUser -Examples

# Get parameter that accepts pipeline input
Get-Help Get-ADUser -Parameter * | 
Where-Object {$_.pipelineInput -match 'true'} | 
Select * 

# List of all parameters that a given cmdlet supports along with a short description:
Get-Help dir -para * | 
Format-Table Name, { $_.Description[0].Text } -wrap


# Find all cmdlets / functions with a target parameter
Get-Command -CommandType Function | 
Where-Object { $_.parameters.keys -match 'credential'} | 
Out-GridView -PassThru -Title 'Available functions which has a specific parameter'

Get-Command -CommandType Cmdlet | 
Where-Object { $_.parameters.keys -match 'credential'} | 
Out-GridView -PassThru -Title 'Results for cmdlets which has a specific parameter'

# Get named aliases 
Get-Alias | 
Out-GridView -PassThru -Title 'Available aliases'

# Get cmdlet / function parameter aliases
(Get-Command Get-ADUser).Parameters.Values | 
where aliases | 
select Name, Aliases | 
Out-GridView -PassThru -Title 'Alias results for a given cmdlet or function.'

### Query Powershell Data Types
[AppDomain]::CurrentDomain.GetAssemblies() | 
Foreach-Object { $_.GetExportedTypes() }

# Or 

[psobject].Assembly.GetType(“System.Management.Automation.TypeAccelerators”)::get

# Or

[psobject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::Get.GetEnumerator() `
| Sort-Object -Property Key

<#
 Get any .NET types and their static methods from PowerShell. 
 Enumerate all that are currently loaded into your AppDomain.
#>  
[AppDomain]::CurrentDomain.GetAssemblies() | 
foreach { $_.GetTypes() } | 
foreach { $_.GetMethods() } | 
where { $_.IsStatic } | 
select DeclaringType, Name | 
Out-GridView -PassThru -Title '.NET types and their static methods'

如前所述,有些东西(不一定总是模块/cmdlet)只是 ISE(当然是 ISE 模块等中的任何东西)取决于你在做什么/做什么,例如很多形式的东西,但只要当您将适当的表单类/类型添加到代码中时,它们也应该在控制台主机中运行良好。

然而,认为标记为 ISE 的任何东西都可以在其他任何地方运行是不正确的。还有很多 ISE 插件。您可以通过 ISE 附加组件菜单访问它们。该菜单中的任何内容都不应该出现在控制台主机中。例如,这是一个内置工具,可直接在 ISE 编辑器选项卡中打开基于文本的文件,psEdit。

Get-Help -Name psedit

NAME
    psEdit
    
SYNTAX
    psEdit [-filenames] <Object>  [<CommonParameters>]
    

ALIASES
    None
    

REMARKS
    None

尝试在控制台主机中使用它会失败,因为控制台主机没有这样的编辑器。

您也可以在 ISE 中以编程方式执行操作,当然这种事情在控制台主机中永远不会起作用。

在此处查看详细信息: ISE 对象模型层次结构

为了确保东西在你需要的时候它应该在哪里,调整你的 PowerShell 配置文件。例如,当我在 ISE 与控制台主机中时,这里有一个我要处理的示例。

# Validate if in the ISE or not

If ($Host.Name -match 'ISE')
{
    Import-Module -Name PsISEProjectExplorer
    Import-Module -Name PSharp
    Import-Module -Name ClassExplorer

}

If ($Host.Name -notmatch 'ISE')
{ Import-Module -Name PSReadline }

Import-Module -Name PSScriptAnalyzer
Import-Module -Name Posh-SSH
Import-Module -Name ModuleLibrary -DisableNameChecking
Import-Module -Name Pester
Import-Module -Name PSKoans


If ($Host.Name -match 'ISE')
{
    #Script Browser Begin
    #Version: 1.3.2
    Add-Type -Path 'C:\Program Files (x86)\Microsoft Corporation\Microsoft Script Browser\System.Windows.Interactivity.dll'
    Add-Type -Path 'C:\Program Files (x86)\Microsoft Corporation\Microsoft Script Browser\ScriptBrowser.dll'
    Add-Type -Path 'C:\Program Files (x86)\Microsoft Corporation\Microsoft Script Browser\BestPractices.dll'
    $scriptBrowser = $psISE.CurrentPowerShellTab.VerticalAddOnTools.Add('Script Browser', [ScriptExplorer.Views.MainView], $true)
    $scriptAnalyzer = $psISE.CurrentPowerShellTab.VerticalAddOnTools.Add('Script Analyzer', [BestPractices.Views.BestPracticesView], $true)
    $psISE.CurrentPowerShellTab.VisibleVerticalAddOnTools.SelectedAddOnTool = $scriptBrowser
    #Script Browser End

    Set-StrictMode  -Version Latest 
}

OP 更新

至于……</p>

那么,有没有办法查询在 powershell.exe(或 pwsh.exe)控制台中实际加载和可运行的命令?

不是我认为你在想的那种意义上。您似乎对启动时加载了哪些 cmdlet 有一个概念。那不是一回事。cmdlet 通过模块加载和路径公开。您所期望的是 PowerShell 仅根据您所在的 PowerShell 版本/环境显示模块/cmdlet/函数。这也不是一回事。PowerShell 将有权访问您系统上的所有 .Net 以及已定义路径中的任何内容。无论您是否加载和使用它们,都是另一回事。

Get-Module                # will show you all currently loaded ones.
Get-Module -ListAvailable # Will show all modules installed on your system.

如果您使用的是 PSv3 或更高版本,那么您的系统环境和 PowerShell 路径始终可用,因为您在路径中调用的任何内容都会在您尝试使用它时自动加载。

再次 Get-Command 将列出所有可用的,它们仅在您调用一个时加载,并且在调用或会话完成/关闭时消失。

如果您的模块、cmdlet / 函数不在预期的(环境或 PS 路径)位置,则必须添加该路径或使用它们的 UNC 路径来运行它们。因此,路径中的任何内容(源自任何 UNC 的点源)始终可用。如果您在 ISE 中,您可以在“命令”选项卡中查看此内容,或者使用 Get-Command 在控制台中查看。

您可以通过 PowerShell 配置文件或使用 Windows 环境变量对话框即时或使用 PowerShell 配置文件临时添加路径,或永久添加路径。

控制台主机和 ISE 将始终列出预期路径中的任何模块、cmdlet 功能。它们并不意味着它们都是可用的。如前所述,出于显而易见的原因,特定于 ISe 的模块、cmdlet、函数只能在 ISE 中运行。然而,ISE 将运行控制台主机将运行的任何模块 cmdlet 功能,PSReadline 除外。好吧,它会加载它,但它不会在 ISE 控制台中执行任何操作。ISE 控制台实际上是一个输出窗口,与控制台主机不同。好吧,你可以在里面做控制台主机之类的东西,但这不是一回事。

因此,加载了模块,模块公开了其中的 cmdlet / 函数。并非所有模块都默认加载,因此上述两个命令的原因,这就是 Import-Module 和 auto load on call 存在的原因。独立的个人模块/cmdlet/函数/脚本不是 PS 知道的,除非你告诉它应该从哪里导入/加载/使用它们。

如果您真的对这类事情感到好奇,您可以利用 Trace-Command cmdlet ...

跟踪命令

$A = "i*"
Trace-Command ParameterBinding {Get-Alias $Input} -PSHost -InputObject $A

DEBUG: ParameterBinding Information: 0 : BIND NAMED cmd line args [Get-Alias]
DEBUG: ParameterBinding Information: 0 : BIND POSITIONAL cmd line args [Get-Alias]
DEBUG: ParameterBinding Information: 0 :     BIND arg [System.Object[]] to parameter [Name]
DEBUG: ParameterBinding Information: 0 :         Binding collection parameter Name: argument type [Object[]], parameter type [System.String[]], collection type 
Array, element type [System.String], no coerceElementType
DEBUG: ParameterBinding Information: 0 :         Arg is IList with 1 elements
DEBUG: ParameterBinding Information: 0 :         Creating array with element type [System.String] and 1 elements
DEBUG: ParameterBinding Information: 0 :         Argument type System.Object[] is IList
DEBUG: ParameterBinding Information: 0 :         Adding element of type String to array position 0
DEBUG: ParameterBinding Information: 0 :         BIND arg [System.String[]] to param [Name] SUCCESSFUL
DEBUG: ParameterBinding Information: 0 : MANDATORY PARAMETER CHECK on cmdlet [Get-Alias]
DEBUG: ParameterBinding Information: 0 : CALLING BeginProcessing
DEBUG: ParameterBinding Information: 0 : CALLING EndProcessing

...使用您的代码查看实际调用的内容,您将看到每次运行代码时都会调用它。

您安装的模块越多,云纹 cmdlet / 功能就会变得可用。如果您真的考虑一下,它们就是数百个模块,因此有数千个暴露的 cmdlet / 函数。为什么要将所有内容加载到内存中。您的系统将因资源耗尽而失败。所以,只加载你真正需要的,PowerShell只会在需要的时候调用它需要的。如果您打算住在控制台主机中,或者住在 ISE / VSCode 中,则了解 ISE 的特定内容并忽略所有这些,并且仅在需要时才使用控制台主机。这就是我做事的方式。我很少,如果需要去控制台主机做任何事情。ISE 是我的默认设置,VSCode 是我的辅助设置(目前)。有些人在 ISE 上大便,我不是那些类型的人之一。

OP 更新

至于...

我的用例不是坐在 PC 前的用户,而是运行 powershell.exe (PS5) 或 pwsh.exe (PS6/Core) 主机的 NodeJS 应用程序。我完全明白模块可能是“可用的”但没有加载,这就是我想要查询的:加载了哪些 cmdlet/函数(即现在可以在不加载模块的情况下运行)。我觉得 Get-Command * 会列出 Cmdlet X 但 Get-Command X 会出错,这很奇怪/有问题。如何查询命令:您是否已加载可运行?PS:谷歌“powowshell”查看我的项目。

将链接放入您的项目而不是让我搜索它会有所帮助。 8-}并且它只显示在 Google 而不是其他引擎(如 DuckDuckGo 或 Bing)中的事实有点奇怪,但是哦,好吧。

所以,你的意思是这个系列——

http://cawoodm.blogspot.com https://github.com/cawoodm/powowshell

我会看看。然而,对于你所追求的,不要单独使用 Get-Command。将 Get-Module 与 Get-Command 结合使用,可以列出这些已加载模块中的 cmdlet / 函数,以更接近您的需求。通过这种方式,只会列出该会话的已加载模块和关联的 cmdlet / 函数。

# List all loaded session modules and the exposed cmdlets / functions in them
Get-Module -Name '*' | 
ForEach-Object { Get-Command -Module $PSItem }

# Results

 # List all loaded modules and the exposed cmdlets / functions in them
Get-Module -Name '*' | 
ForEach-Object { Get-Command -Module $PSItem }

CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
... 
Cmdlet          Export-BinaryMiLog                                 1.0.0.0    CimCmdlets
Cmdlet          Get-CimAssociatedInstance                          1.0.0.0    CimCmdlets
Cmdlet          Get-CimClass                                       1.0.0.0    CimCmdlets
...
Cmdlet          Find-Member                                        1.1.0      ClassExplorer
Cmdlet          Find-Namespace                                     1.1.0      ClassExplorer
Cmdlet          Find-Type                                          1.1.0      ClassExplorer
...
Function        Get-IseSnippet                                     1.0.0.0    ISE
Function        Import-IseSnippet                                  1.0.0.0    ISE
Function        New-IseSnippet                                     1.0.0.0    ISE
Cmdlet          Add-Computer                                       3.1.0.0    Microsoft.PowerShell.Management
Cmdlet          Add-Content                                        3.1.0.0    Microsoft.PowerShell.Management
Cmdlet          Checkpoint-Computer                                3.1.0.0    Microsoft.PowerShell.Management                                   
...

OP 更新

至于...

您的解决方案将无法列出没有模块关联(我的系统上为 64)的 cmdlet/函数(例如 ForEach-Object 或 Stop-Job)。另外,您如何确定 Get-Module 仅返回已加载的模块?

PowerShell 从 PowerShell 源和模块中获取 cmdlet 和函数。

如果您对所指向的 cmdlet / 函数进行查找,您将看到它们来自这里

'ForEach-Object','Start-Job' | 
    ForEach{
                Get-Command -CommandType Cmdlet -Name $PSItem | 
                Format-Table -AutoSize
           }

<#
CommandType Name           Version Source                   
----------- ----           ------- ------                   
Cmdlet      ForEach-Object 3.0.0.0 Microsoft.PowerShell.Core



CommandType Name      Version Source                   
----------- ----      ------- ------                   
Cmdlet      Start-Job 3.0.0.0 Microsoft.PowerShell.Core
#>

因此,基本 cmdlet / 功能不是来自 Import-Module 的工作。OS/.Net 安装中的设计就是这样。

所以,我的解决方案不是失败的,我从来没有说过使用它会让你 100% 受益。这是一种向您展示加载哪些模块以使用哪些 cmdlet/函数的方式,这与 Microsoft.PowerShell.Core、.Net 整体和/或操作系统版本允许的内容几乎没有关系(Cmdlets/Functions/Modules 是也是我们都知道的特定于操作系统和 $PSVersion 的)。

因此,同样,您尝试设计的用例是无效的。无论来源如何,Cmdlet 和函数都未加载并可供使用。当您需要通过上述方式调用它们时,它们已安装或暴露并可供使用。在您调用它们之前,它们永远不会被加载(位于内存中),与 GAC 中的任何东西都不一样。

所以,看着你的项目,我明白你在做什么,但你是在为用户着想。就像您作为开发人员必须从 GAC 引用一个程序集(其中有成千上万的东西,但在您引用它们之前不会加载),您必须知道它在哪里以及您想使用哪个为什么。因此,对于 PowerShell 可以访问的内容也是如此。请注意,我说的是访问权限,而不是您是否可以在 PowerShell 会话中使用它。

所以,如果我们踏入这一步,我们会得到...

Cmdlets / Function come from. The OS (DLLs), [.Net][4], [Core module][3], and those exported from the modules you Import.

因此,您再次认为,在导入模块或 DLL 时,什么是可用的或可用的。导入的模块及其相关的 cmdlet / 功能可能不起作用,具体取决于您使用的会话类型。意思是 ISE 与 consolhost。

仅供参考,你必须扩大你对这个的看法......

在 ISE

# Total host available commands cmdlet / Functions regadless where the come from
(Get-Command).Count
8750
# Total host avaialble cmdlets
(Get-Command -CommandType Cmdlet).Count
4772
# Total host available functions
(Get-Command -CommandType Function).Count
3035

# Difference of host available cmdlets / functions not shown that are part of the previous two calls.
(Get-Command).Count - ((Get-Command -CommandType Cmdlet).Count + (Get-Command -CommandType Function).Count)
943

# Further breakdown
(Get-Command -CommandType Alias).Count
1446
(Get-Command -CommandType Application).Count
937
(Get-Command -CommandType Configuration).Count
# The property 'Count' cannot be found on this object. Verify that the property exists.
(Get-Command -CommandType ExternalScript).Count
2
(Get-Command -CommandType Script).Count
# The property 'Count' cannot be found on this object. Verify that the property exists.
(Get-Command -CommandType Filter).Count
2
(Get-Command -CommandType Workflow).Count
# The property 'Count' cannot be found on this object. Verify that the property exists.
(Get-Command -CommandType All).Count
10219


# Get a list of all Modules
(Get-Module -ListAvailable).Count
387

# Get a list of all loaded Modules
(Get-Module).Count
12

# List all loaded session modules and the exposed cmdlets / functions in them
(Get-Module -Name '*' | 
ForEach-Object { Get-Command -Module $PSItem }).Count
505

(Get-Module -ListAvailable | 
ForEach {
    Get-Module -Name $PSItem.Name | 
    ForEach-Object { Get-Command -Module $PSItem }
}).Count
669



# If I Import another 3rdP module I installed from the gallery, things will change of course

Import-Module -Name ShowUI

# Get a list of all Modules
(Get-Module -ListAvailable).Count
387

# Get a list of all loaded Modules
(Get-Module).Count
13

# List all loaded session modules and the exposed cmdlets / functions in them
(Get-Module -Name '*' | 
ForEach-Object { Get-Command -Module $PSItem }).Count
937

(Get-Module -ListAvailable | 
ForEach {
    Get-Module -Name $PSItem.Name | 
    ForEach-Object { Get-Command -Module $PSItem }
}).Count
1101

在控制台主机中 - 注意差异

# Total host available commands cmdlet / Functions regadless where the come from
(Get-Command).Count
9191

# Total host avaialble cmdlets
(Get-Command -CommandType Cmdlet).Count
4772

# Total host available functions
(Get-Command -CommandType Function).Count
3472

# Difference of host available cmdlets / functions not shown that are part of the previous two calls.
(Get-Command).Count - ((Get-Command -CommandType Cmdlet).Count + (Get-Command -CommandType Function).Count)
947


# Further breakdown
(Get-Command -CommandType Alias).Count
1809

(Get-Command -CommandType Application).Count
937

(Get-Command -CommandType Configuration).Count
0
# The property 'Count' cannot be found on this object. Verify that the property exists.
(Get-Command -CommandType ExternalScript).Count
2

(Get-Command -CommandType Script).Count
0
# The property 'Count' cannot be found on this object. Verify that the property exists.
(Get-Command -CommandType Filter).Count
1

(Get-Command -CommandType Workflow).Count
1
# The property 'Count' cannot be found on this object. Verify that the property exists.
(Get-Command -CommandType All).Count
10994




# Get a list of all Modules
(Get-Module -ListAvailable).Count
387

# Get a list of all loaded Modules
(Get-Module).Count
8

# List all loaded session modules and the exposed cmdlets / functions in them
(Get-Module -Name '*' | 
ForEach-Object { Get-Command -Module $PSItem }).Count
467

(Get-Module -ListAvailable | 
ForEach {
    Get-Module -Name $PSItem.Name | 
    ForEach-Object { Get-Command -Module $PSItem }
}).Count
623



# If I Import another 3rdP module I installed from the gallery, things will change of course

Import-Module -Name ShowUI

# Get a list of all Modules
(Get-Module -ListAvailable).Count
387


# Get a list of all loaded Modules
(Get-Module).Count
9


# List all loaded session modules and the exposed cmdlets / functions in them
(Get-Module -Name '*' |
ForEach-Object { Get-Command -Module $PSItem }).Count
899


(Get-Module -ListAvailable |
ForEach {
    Get-Module -Name $PSItem.Name |
    ForEach-Object { Get-Command -Module $PSItem }
}).Count
1055

推荐阅读