繁体   English   中英

如何在powershell中列出所有已安装、可运行的cmdlet?

[英]How to list all installed, runnable cmdlets in powershell?

我想在 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 中列出所有已安装、可运行的 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 更新

至于……

那么,有没有办法查询在 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 配置文件临时添加路径,也可以通过 PowerShell 配置文件或使用 Windows 环境变量对话框永久添加路径。

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

因此,模块被加载,模块公开其中的 cmdlet/函数。 并非所有模块都默认加载,因此上面两个命令的原因,这就是导入模块和调用时自动加载的原因。 独立的个人模块/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 / 函数不是来自导入模块的工作。 在 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

不幸的是,正如您所发现的, PowerShell 的命令发现(由Get-Command )也可能包括您实际上无法在会话中运行的命令

这样做有充分的理由,也有不那么充分的理由:

  • (a) 来自需要或可能需要不同PowerShell版本的模块的命令仍然包括在内,唯一的例外是$PSHOME/Modules Windows - Windows 上其他目录中的模块和类 Unix 平台上的所有模块$env:PSModulePath总是被认为是兼容的 - 从 PowerShell Core 6.2.1 开始,不会查阅PSCompatibleEdition模块清单条目。

  • (b) 从 PowerShell Core 6.2.1 / Windows PowerShell v5.1 开始,无法通过支持的平台 (OS)来限制模块

  • (c) 在命令发现期间不检查PowerShellHostNamePowerShellHostVersion模块清单条目的兼容性以确保PowerShell 主机兼容性- 仅在模块导入时

(a) 是一个设计决定(至少现在是这样),(b) 尚未实施,但是(c) - 您遇到的问题 - 应该可以说是固定的,因为它很容易执行。 我鼓励您在https://github.com/PowerShell/PowerShell/issues请求更改。

一般来说,命令发现必须限于检查模块清单以确定兼容性; 除此之外的任何事情 - 尝试实际加载每个模块 - 都将耗费大量时间和资源。


更令人困惑的是,从 PowerShell Core 6.2.1 / Windows PowerShell v5.1 开始,带有文字命令名称的Get-Command报告误导性错误消息

通配符表达式(例如, *-* )不同,文字命令名称(例如, New-IseSnippet )导致Get-Command隐式导入命令的模块,这是对当前会话中命令可用性的最终测试 - 和那可能会失败

不幸的是,它错误地失败的方式表明没有定义这样的命令,而真正的问题是无法导入包含该命令的模块

直接调用相同的命令更有帮助表明真正的问题是无法导入模块(尽管,可以说,它不应该只是告诉您自己运行Import-Module以了解具体原因,而是这样做为您,然后报告该原因)。

我已经为您编写了两个函数,它们将帮助您枚举可以在您的系统上运行的所有已安装命令。

Get-CommandsByModule :按类型(由-CommandType开关中的所有可用类型定义)枚举模块中的每个可用命令。 这还将按类型显示每个模块的项目计数,并且在枚举所有模块中的所有命令后,将显示系统上安装的每种类型的总命令摘要。 很容易扩展此函数以测试每个命令以查看该命令在收集它们时是否有效(尽管这会大大减慢该函数的速度)。 要仅查看某种类型的命令,您可以使用带参数的函数运行,例如

Get-CommandsByModule     # Will output all types of command found in each Module
Get-CommandsByModule function,cmdlet,alias   # Just display functions, cmdlets and aliases

def :主要用于函数和别名(尽管会显示所有命令类型的信息),这将显示该函数/别名的内容/定义以及它所在的模块。

def <any-command>   # command can be cmdlet, function, alias, etc

函数 Get-CommandsByModule:

function Get-CommandsByModule ($usertype) {
    function Write-Wrap {
        [CmdletBinding()]
        Param ( 
            [parameter (Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName)]
            [Object[]] $chunk
        )
        PROCESS {
            $Lines = @()
            foreach ($line in $chunk) {
                $str = ''
                $counter = 0
                $line -split '\s+' | %{
                    $counter += $_.Length + 1
                    if ($counter -gt $Host.UI.RawUI.BufferSize.Width) {
                        $Lines += ,$str.trim()
                        $str = ''
                        $counter = $_.Length + 1
                    }
                    $str = "$str$_ "
                }
                $Lines += ,$str.trim()
            }
            $Lines
        }
    }
    
    $types = @("Alias", "Function", "Filter", "Cmdlet", "ExternalScript", "Application", "Script", "Workflow", "Configuration")
    if ($null -ne $usertype) { $types = @($usertype)}
    foreach ($type in $types) { New-Variable -Name $type -Value 0 }   # Dynamically generated variables
    foreach ($mod in Get-Module -ListAvailable) {
        "`n`n####################`n#`n# Module: $mod`n#`n####################`n"
        foreach ($type in $types) {
            $out = ""
            $commands = gcm -Module $mod -CommandType $type | sort
            foreach ($i in $commands) {
                $out = "$out, $i"
            }
            $count = ($out.ToCharArray() | Where-Object { $_ -eq ',' } | Measure-Object).Count   # Could just count $i but this is 

            if ($count -ne 0) {
                $out = $out.trimstart(", ")
                $out = "`n$($type.ToUpper()) objects [ $count ] >>> $out"
                Write-Wrap $out
                # Example of using New-, Set-, Get-Variable for dynamically generated variables
                Set-Variable -Name $type -Value $((Get-Variable -Name $type).Value + $count)
                # https://powershell.org/forums/topic/two-variables-into-on-variable/
                # "$type Total = $total"
                ""
            }
        }
    }
    ""
    "`n`n####################`n#`n# Commands by type installed on this system`n#`n####################`n"
    foreach ($type in $types) { "Total of type '$type' = $((Get-Variable -Name $type).Value)" }
}

功能定义:

function def {   
    [CmdletBinding()]
    param (
        [Parameter(Mandatory)]
        [ArgumentCompleter({ [Management.Automation.CompletionResult]::Command })]
        [string]$cmd,
        [switch]$Examples
    )

    function Write-Wrap {
        [CmdletBinding()]Param( [parameter(Mandatory=1, ValueFromPipeline=1, ValueFromPipelineByPropertyName=1)] [Object[]]$chunk )
        $Lines = @()
        foreach ($line in $chunk) {
            $str = ''; $counter = 0
            $line -split '\s+' | % {
                $counter += $_.Length + 1
                if ($counter -gt $Host.UI.RawUI.BufferSize.Width) {
                    $Lines += ,$str.trim()
                    $str = ''
                    $counter = $_.Length + 1
                }
                $str = "$str$_ "
            }
            $Lines += ,$str.trim()
        }
        $Lines
    }

    $deferr = 0; $type = ""
    try { $type = ((gcm $cmd -EA silent).CommandType); if ($null -eq $type) { $deferr = 1 } } catch { $deferr = 1 }

    if ($deferr -eq 1) {
        if ($cmd -eq $null) { Write-Host "Object is `$null" ; return } 
        Write-Host "`$object | Convert-Json:" -F Cyan
        $cmd | ConvertTo-Json
        ""
        Write-Host "(`$object).GetType()" -F Cyan -NoNewline ; Write-Host " :: [BaseType|Name|IsPublic|IsSerial|Module]"
        ($cmd).GetType() | % { "$($_.BaseType), $($_.Name), $($_.IsPublic), $($_.IsSerializable), $($_.Module)" }
        ""
        Write-Host "`$object | Get-Member -Force" -F Cyan
        $m = "" ; $cm = "" ; $sm = ""; $p = "" ; $ap = "" ; $cp = "" ; $np = "" ; $pp = "" ; $sp = "" ; $ms = ""
        $msum = 0 ; $cmsum = 0 ; $smsum = 0 ; $psum = 0 ; $cpsum = 0 ; $apsum = 0 ; $spsum = 0 ; $ppsum = 0 ; $npsum = 0 ; $spsum = 0 ; $mssum = 0
        $($cmd | Get-Member -Force) | % {
            if ($_.MemberType -eq "Method") { if(!($m -like "*$($_.Name),*")) { $m += "$($_.Name), " ; $msum++ } }
            if ($_.MemberType -eq "CodeMethod") { if(!($cm -like "*$($_.Name),*")) { $cm += "$($_.Name), " ; $cmsum++ } }
            if ($_.MemberType -eq "ScriptMethod") { if(!($sm -like "*$($_.Name),*")) { $sm += "$($_.Name), " ; $smsum++ } }
            if ($_.MemberType -eq "Property") { if(!($p -like "*$($_.Name),*")) { $p += "$($_.Name), " ; $psum++ } }
            if ($_.MemberType -eq "AliasProperty") { if(!($ap -like "*$($_.Name),*")) { $ap += "$($_.Name), " ; $apsum++ } }
            if ($_.MemberType -eq "CodeProperty") { if(!($cp -like "*$($_.Name),*")) { $cp += "$($_.Name), " ; $cpsum++ } }
            if ($_.MemberType -eq "NoteProperty") { if(!($np -like "*$($_.Name),*")) { $np += "$($_.Name), " ; $npsum++ } }
            if ($_.MemberType -eq "ParameterizedProperty") { if(!($pp -like "*$($_.Name),*")) { $pp += "$($_.Name), " ; $ppsum++} }
            if ($_.MemberType -eq "ScriptProperty") { if(!($sp -like "*$($_.Name),*")) { $sp += "$($_.Name), " ; $npsum++ } }
            if ($_.MemberType -eq "MemberSet") { if(!($ms -like "*$($_.Name),*")) { $ms += "$($_.Name), " ; $mssum++ } }
            # AliasProperty, CodeMethod, CodeProperty, Method, NoteProperty, ParameterizedProperty, Property, ScriptMethod, ScriptProperty
            # All, Methods, MemberSet, Properties, PropertySet
        }
        if($msum -ne 0) { Write-Wrap ":: Method [$msum] => $($m.TrimEnd(", "))" }
        if($msum -ne 0) { Write-Wrap ":: CodeMethod [$cmsum] => $($cm.TrimEnd(", "))" }
        if($msum -ne 0) { Write-Wrap ":: ScriptMethod [$smsum] => $($sm.TrimEnd(", "))" }
        if($psum -ne 0) { Write-Wrap ":: Property [$psum] => $($p.TrimEnd(", "))" }
        if($npsum -ne 0) { Write-Wrap ":: AliasProperty [$apsum] => $($ap.TrimEnd(", "))" }
        if($npsum -ne 0) { Write-Wrap ":: CodeProperty [$cpsum] => $($cp.TrimEnd(", "))" }
        if($npsum -ne 0) { Write-Wrap ":: NoteProperty [$npsum] => $($np.TrimEnd(", "))" }
        if($ppsum -ne 0) { Write-Wrap ":: ParameterizedProperty [$ppsum] => $($pp.TrimEnd(", "))" }
        if($spsum -ne 0) { Write-Wrap ":: ScriptProperty [$spsum] => $($sp.TrimEnd(", "))" }
        if($mssum -ne 0) { Write-Wrap ":: ScriptProperty [$mssum] => $($ms.TrimEnd(", "))" }
        ""
        Write-Host "`$object | Measure-Object" -F Cyan
        $cmd | Measure-Object | % { "Count [$($_.Count)], Average [$($_.Average)], Sum [$($_.Sum)], Maximum [$($_.Maximum)], Minimum [$($_.Minimum)], Property [$($_.Property)]" }
    }

    if ($deferr -eq 0) {

        if ($cmd -like '*`**') { Get-Command $cmd ; break }   # If $cmd contains a *, then just check for commands, don't find definitions

        if ($type -eq 'Cmdlet') {
            Write-Host "`n'$cmd' is a Cmdlet:`n" -F Green
            Write-Host "SYNOPSIS, DESCRIPTION, SYNTAX for '$cmd'.   " -F Green
            Write-Host "------------"
            Write-Host ""
            Write-Host "(Get-Help $cmd).Synopsis" -F Cyan 
            Write-Host "$((Get-Help $cmd).Synopsis)"
            Write-Host ""
            Write-Host "(Get-Help $cmd).Description.Text" -F Cyan
            try {
                $arrdescription = (Get-Help $cmd).Description.Text.split("`n")
                foreach ($i in $arrdescription) { Write-Wrap $i }
            } catch { "Could not resolve description for $cmd" }
            Write-Host ""
            Write-Host "(Get-Command $cmd -Syntax)" -F Cyan
            $arrsyntax = (Get-Command $cmd -syntax).TrimStart("").Split("`n")  # Trim empty first line then split by line breaks
            foreach ($i in $arrsyntax) { Write-Wrap $i }   # Wrap lines properly to console width
            Get-Alias -definition $cmd -EA silent          # Show all defined aliases
            Write-Host "`nThis Cmdlet is in the '$((Get-Command -type cmdlet $cmd).Source)' Module." -F Green
            Write-Host ""
            Write-Host ""
        }
        elseif ($type -eq 'Alias') {
            Write-Host "`n'$cmd' is an Alias.  " -F Green -NoNewLine ; Write-Host "This Alias is in the '$((get-command -type alias $cmd).ModuleName).' Module"
            Write-Host ""
            Write-Host "Get-Alias '$cmd'   *or*    cat alias:\$cmd" -F Cyan
            cat alias:\$cmd   # Write-Host "$(cat alias:\$cmd)"   # "$((Get-Alias $cmd -EA silent).definition)"
            if ($cmd -eq '?') { $cmd = '`?' }   # To deal correctly with the wildcard '?'
            "`n'$((Get-Alias $cmd).Name)' is an alias of '$((Get-Alias $cmd).ReferencedCommand)'"
            $fulldef = (Get-Alias $cmd -EA silent).definition   # Rerun def but using the full cmdlet or function name.
            def $fulldef
            if ($Examples -eq $true) { $null = Read-Host 'Press any key to view command examples' ; get-help $fulldef -examples }
        }
        elseif ($type -eq 'Function') {
            Write-Host "`n'$cmd' is a Function.  " -F Green -NoNewline
            Write-Host "`ncat function:\$cmd   (show contents of function)`n" -F Cyan ; cat function:\$cmd ; Write-Host ""
            Write-Host "cat function:\$cmd`n" -F Cyan
            Write-Host ""
            Write-Host "SYNOPSIS, SYNTAX for '$cmd'.   " -F Green
            Write-Host "------------"
            $arrsynopsis = ((Get-Help $cmd).Synopsis).TrimStart("").Split("`n")  # Trim empty first line then split by line breaks
            $arrsyntax = (Get-Command $cmd -syntax).TrimStart("").Split("`n")    # Often synopsis=syntax for function so use Compare-Object
            if ($null -eq $(Compare-Object $arrsynopsis $arrsyntax -SyncWindow 0)) { 
                Write-Host "'(Get-Help $cmd).Synopsis'" -F Cyan -N
                Write-Host " and " -N
                Write-Host "'Get-Command $cmd -Syntax'" -F Cyan -N
                Write-Host " have the same output for this function:`n"
                foreach ($i in $arrsynopsis) { Write-Wrap $i }   # Wrap lines properly to console width
            } else { 
                Write-Host "(Get-Help $cmd).Synopsis" -F Cyan
                foreach ($i in $arrsynopsis) { Write-Wrap $i }   # Wrap lines properly to console width
                Write-Host ""
                Write-Host "Get-Command $cmd -Syntax" -F Cyan
                foreach ($i in $arrsyntax) { Write-Wrap $i }     # Wrap lines properly to console width
            }
            Write-Host "The '$cmd' Function is in the '$((get-command -type function $cmd).Source)' Module." -F Green
            Write-Host ""
            if ($Examples -eq $true) { $null = Read-Host "Press any key to view command examples" ; get-help $cmd -examples }
            Write-Host ""
        }
        elseif ($type -eq 'ExternalScript') {   # For .ps1 scripts on path
            $x = gcm $cmd
            Write-Host "`n'$cmd' is an ExternalScript (i.e. a .ps1 file on the path)." -F Green
            Write-Host "`n$($x.Path)`n" -F Green
            Write-Host "`n$($x.ScriptContents)"
            Write-Host ""
            if ($Examples -eq $true) { $null = Read-Host "Press any key to view command examples" ; get-help $cmd -Examples }
            elseif ($Synopsis -eq $true) { $null = Read-Host "Press any key to view command examples" ; (get-help $cmd).Synopsis }
            elseif ($Syntax -eq $true) { $null = Read-Host "Press any key to view command examples" ; Get-Command $cmd -Syntax }
            Write-Host ""
        }
        elseif ($type -eq 'Application') {      # For .exe etc on path
            Write-Host "`n'$cmd' was found. It is an Application (i.e. a .exe or similar located on the path)." -F Green
            Write-Host "`n$(where.exe $cmd)" -F Green
            Write-Host ""
            Read-Host "Press any key to open cmd.exe and try '$cmd /?'" ; cmd.exe /c $cmd /? | more
            Write-Host ""
        }
    } elseif ((get-module -ListAvailable -Name $cmd) -ne $null) {
        # https://stackoverflow.com/questions/28740320/how-do-i-check-if-a-powershell-module-is-installed
        ""
        (get-module $cmd).path
        (get-module $cmd).ExportedFunctions
        "ExportedCommands (also note: get-command -Module $cmd)"
        (get-module custom-tools).ExportedCommands
        ""
        echo "get-module $cmd | get-member  # Just show the members"
        echo "get-module $cmd | fl *        # Show the contents of every member"
    }
    else {
        if ($cmd.length -eq 0) { "`n'$cmd': No command definition found. The command may require to be surround by ' or `"`nif it contains special characters (such as 'def `"&`"').`n" }
        else { "`nInput is not a command, so no command definition search.`n" }
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM