簡體   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