[Request]: Improved usage of Get-ModuleCommand
jaols opened this issue · comments
Describe the request
Hi Jeff,
I have a similar function as Get-ModuleCommand in my module PSJumpStart - Get-ModuleHelp. I have just re-written my function inspired by yours. The main difference between them is that you may search for a command by using "CommandName" either in installed modules or "-ListAvailable".
Please feel free to use whatever you think is usefull from my function, and thank you for the inspiration of using PSCustomObjects as output making the help more useful.
All the best!
Jack Olsson
jackgolsson@gmail.com
Function Get-ModuleHelp {
<#
.Synopsis
Get commands from specific module(s) or a list of modules
.DESCRIPTION
Retreive all module names or commands filtered by name and/or command name.
.PARAMETER Name
Use module name filter option to limit help information to specific module(s). Supports wildcards
.PARAMETER CommandName
Retreive comnmand information from all modules or from specifc module(s). Supports wildcards
.PARAMETER ListAvailable
Expand scope to include available modules (not only installed)
.NOTES
Author: Jack Olsson (Inspired by Jeff Hicks - Get-ModuleCommand)
.EXAMPLE
Get-ModuleHelp -Name PSJumpStart
List all exported commands for the 'PSJumpStart' module
.EXAMPLE
Get-ModuleHelp -CommandName "*address*"
Get all coomands containing 'address' from installed modules
.EXAMPLE
Get-ModuleHelp -CommandName *clip* -ListAvailible
List all available modules with commands containing the string 'clip'.
.EXAMPLE
Get-ModuleHelp -Name "*PowerShell*" -ListAvailible
List all modules containing the name 'PowerShell'
.EXAMPLE
Get-ModuleHelp
List instelled modules
#>
[cmdletbinding(DefaultParameterSetName = "name")]
[Alias("gmh")]
[OutputType("ModuleHelp")]
Param(
[Parameter(
Position = 0,
HelpMessage = "The name of an installed/available module",
ValueFromPipelineByPropertyName
)]
[SupportsWildcards()]
[string]$Name,
[Parameter(
HelpMessage = "Command name to search for"
)]
[SupportsWildcards()]
[string]$CommandName,
[switch]$ListAvailable
)
Begin {
Write-Verbose "Starting $($MyInvocation.MyCommand)"
$PSBoundParameters.Add("ErrorAction", "stop")
#region local functions
function getModuleInfo {
[cmdletbinding()]
param(
$module,
$CommandName
)
Write-Verbose "Using version $($module.version)"
$cmds = @()
Write-Verbose "Getting exported functions"
$cmds += $module.Exportedfunctions.keys | Where-Object { $_ -like "$CommandName" } | Get-Command
Write-Verbose "Getting exported cmdlets"
$cmds += $module.Exportedcmdlets.keys | Where-Object { $_ -like "$CommandName" } | Get-Command
Write-Verbose "Found $($cmds.count) functions and/or cmdlets"
$out = foreach ($cmd in $cmds) {
Write-Verbose "Processing $($cmd.name)"
#get aliases, ignoring errors for those commands without one
$alias = (Get-Alias -Definition $cmd.Name -ErrorAction SilentlyContinue).name
#it is assumed you have updated help
[PSCustomObject]@{
PSTypeName = "ModuleHelp"
Name = $cmd.name
Alias = $alias
Verb = $cmd.verb
Noun = $cmd.noun
Synopsis = (Get-Help $cmd.name -ShowWindow:$false).synopsis.trim()
Type = $cmd.CommandType
Version = $cmd.version
Help = $cmd.HelpUri
ModuleName = $module.name
ModulePath = $module.Path
Compatible = $module.CompatiblePSEditions
PSVersion = $module.PowerShellVersion
}
} #foreach cmd
$out
}
#endregion
}
Process {
If ([string]::IsNullOrEmpty($Name) -and [string]::IsNullOrEmpty($CommandName)) {
if ($ListAvailable) {
$out = Get-Module -ListAvailable | ForEach-Object {
[PSCustomObject]@{
PSTypeName = "ModuleHelp"
Name = $_.name
Alias = ""
Verb = ""
Noun = ""
Synopsis = $_.Description
Type = $null
Version = $_.version
Help = $_.HelpInfoUri
ModuleName = "Available Modules"
ModulePath = $_.Path
Compatible = $_.CompatiblePSEditions
PSVersion = $_.PowerShellVersion
}
}
}
else {
$out = Get-InstalledModule | ForEach-Object {
[PSCustomObject]@{
PSTypeName = "ModuleCommand"
Name = $_.name
Alias = ""
Verb = ""
Noun = ""
Synopsis = $_.Description
Type = $null
Version = $_.version
Help = $_.HelpInfoUri
ModuleName = "Installed Modules"
ModulePath = $_.Path
Compatible = $_.CompatiblePSEditions
PSVersion = $_.PowerShellVersion
}
}
}
}
else {
if ([string]::IsNullOrEmpty($CommandName)) { $CommandName = "*" }
if ([string]::IsNullOrEmpty($Name)) { $Name = "*" }
if ($ListAvailable) {
$out = Get-Module -Name $Name -ListAvailable | ForEach-Object {
#We need to rebind to object (reason unknown!!)
getModuleInfo -module $_ -CommandName $CommandName
}
}
else {
$out = Get-Module -Name $Name | ForEach-Object {
getModuleInfo -module $_ -CommandName $CommandName
}
}
}
#display results sorted by name for better formatting
$out | Sort-Object -Property ModuleName, Name
}
End {
Write-Verbose "Ending $($MyInvocation.MyCommand)"
}
}
PowerShell version
None
Platform
None
Function Get-ModuleCommand {
<#
.Synopsis
Get commands from specific module(s) or a list of modules
.DESCRIPTION
Retreive all module names or commands filtered by name and/or command name.
.PARAMETER Name
Use module name filter option to limit help information to specific module(s). Supports wildcards
.PARAMETER CommandName
Retreive comnmand information from all modules or from specifc module(s). Supports wildcards
.PARAMETER ListAvailable
Expand scope to include available modules (not only installed)
.EXAMPLE
Get-ModuleCommand -Name PSScriptTools
List all exported commands for the 'PSScriptTools' module
.EXAMPLE
Get-ModuleCommand -CommandName "*address*"
Get all coomands containing 'address' from installed modules
.EXAMPLE
Get-ModuleCommand -CommandName *clip* -ListAvailible
List all available modules with commands containing the string 'clip'.
.EXAMPLE
Get-ModuleCommand -Name "*PowerShell*" -ListAvailible
List all modules containing the name 'PowerShell'
.EXAMPLE
Get-ModuleCommand
List instelled modules
#>
[cmdletbinding(DefaultParameterSetName = "name")]
[Alias("gmh")]
[OutputType("ModuleCommand")]
Param(
[Parameter(
Position = 0,
HelpMessage = "The name of an installed/available module",
ValueFromPipelineByPropertyName
)]
[SupportsWildcards()]
[string]$Name,
[Parameter(
HelpMessage = "Command name to search for"
)]
[SupportsWildcards()]
[string]$CommandName,
[switch]$ListAvailable
)
Begin {
Write-Verbose "Starting $($MyInvocation.MyCommand)"
$PSBoundParameters.Add("ErrorAction", "stop")
#region local functions
function getModuleInfo {
[cmdletbinding()]
param(
$module,
$CommandName
)
Write-Verbose "Using version $($module.version)"
$cmds = @()
Write-Verbose "Getting exported functions"
$cmds += $module.Exportedfunctions.keys | Where-Object { $_ -like "$CommandName" } | Get-Command
Write-Verbose "Getting exported cmdlets"
$cmds += $module.Exportedcmdlets.keys | Where-Object { $_ -like "$CommandName" } | Get-Command
Write-Verbose "Found $($cmds.count) functions and/or cmdlets"
$out = foreach ($cmd in $cmds) {
Write-Verbose "Processing $($cmd.name)"
#get aliases, ignoring errors for those commands without one
$alias = (Get-Alias -Definition $cmd.Name -ErrorAction SilentlyContinue).name
#it is assumed you have updated help
[PSCustomObject]@{
PSTypeName = "ModuleCommand"
Name = $cmd.name
Alias = $alias
Verb = $cmd.verb
Noun = $cmd.noun
Synopsis = (Get-Help $cmd.name -ShowWindow:$false).synopsis.trim()
Type = $cmd.CommandType
Version = $cmd.version
Help = $cmd.HelpUri
ModuleName = $module.name
ModulePath = $module.Path
Compatible = $module.CompatiblePSEditions
PSVersion = $module.PowerShellVersion
}
} #foreach cmd
$out
}
#endregion
}
Process {
If ([string]::IsNullOrEmpty($Name) -and [string]::IsNullOrEmpty($CommandName)) {
if ($ListAvailable) {
$out = Get-Module -ListAvailable | ForEach-Object {
[PSCustomObject]@{
PSTypeName = "ModuleCommand"
Name = $_.name
Alias = ""
Verb = ""
Noun = ""
Synopsis = $_.Description
Type = $null
Version = $_.version
Help = $_.HelpInfoUri
ModuleName = "Available Modules"
ModulePath = $_.Path
Compatible = $_.CompatiblePSEditions
PSVersion = $_.PowerShellVersion
}
}
}
else {
$out = Get-InstalledModule | ForEach-Object {
[PSCustomObject]@{
PSTypeName = "ModuleCommand"
Name = $_.name
Alias = ""
Verb = ""
Noun = ""
Synopsis = $_.Description
Type = $null
Version = $_.version
Help = $_.HelpInfoUri
ModuleName = "Installed Modules"
ModulePath = $_.Path
Compatible = $_.CompatiblePSEditions
PSVersion = $_.PowerShellVersion
}
}
}
}
else {
if ([string]::IsNullOrEmpty($CommandName)) { $CommandName = "*" }
if ([string]::IsNullOrEmpty($Name)) { $Name = "*" }
if ($ListAvailable) {
$out = Get-Module -Name $Name -ListAvailable | ForEach-Object {
#We need to rebind to object (reason unknown!!)
getModuleInfo -module $_ -CommandName $CommandName
}
}
else {
$out = Get-Module -Name $Name | ForEach-Object {
getModuleInfo -module $_ -CommandName $CommandName
}
}
}
#display results sorted by name for better formatting
$out | Sort-Object -Property ModuleName, Name
}
End {
Write-Verbose "Ending $($MyInvocation.MyCommand)"
}
} #close function
Register-ArgumentCompleter -CommandName Get-ModuleCommand -ParameterName Name -ScriptBlock {
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
(Get-Module -Name "$wordtoComplete*").name |
ForEach-Object {
# completion text,listitem text,result type,Tooltip
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}
I'm not sure where to begin with this. I am inclined to close this as an issue. I am very happy to look at a PR if you want to update the command in this module.