Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update Get-ModuleCommand #153

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
230 changes: 147 additions & 83 deletions functions/Get-ModuleCommand.ps1
Original file line number Diff line number Diff line change
@@ -1,118 +1,182 @@
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("gmc")]
[Alias("gmh")]
[OutputType("ModuleCommand")]

Param(
[Parameter(
Position = 0,
Mandatory,
HelpMessage = "The name of an installed module",
ParameterSetName = "name",
Position = 0,
HelpMessage = "The name of an installed/available module",
ValueFromPipelineByPropertyName
)]
[ValidateNotNullOrEmpty()]
[SupportsWildcards()]
[string]$Name,

[Parameter(
Mandatory,
HelpMessage = "The fully qualified name of an installed module",
ParameterSetName = "fqdn"
[Parameter(
HelpMessage = "Command name to search for"
)]
[ValidateNotNullOrEmpty()]
[Microsoft.PowerShell.Commands.ModuleSpecification]$FullyQualifiedName,
[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 {
#getting commands directly from the module because for some unknown reason,
#probably scope related, when using Get-Command alone to list commands in the module,
#it includes private functions

Try {
Write-Verbose "Listing all matching modules"
Write-Verbose "Using bound parameters"
$PSBoundParameters | Out-String | Write-Verbose

#get newest version of the module
$mod = Get-Module @PSBoundParameters | Select-Object -First 1
Write-Verbose "Found $($mod.count) modules"
if (-not $mod) {
Throw "Failed to find a matching module. Try again using the -ListAvailable parameter."
}
#get prerelease from private data
if ($mod.PrivateData -and $mod.PrivateData.ContainsKey('PSData') -and $mod.PrivateData.PSData.ContainsKey('PreRelease')) {
$prerelease = $mod.PrivateData.PSData.PreRelease
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 {
$prerelease = $null
$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
}
}
}
} #try
Catch {
Write-Verbose "This is weird. There was an exception!"
Throw $_
#Bail out
return
}

if ($PSCmdlet.parameterSetName -eq 'name' -AND $mod.count -gt 1) {
#make sure to get the latest version
Write-Verbose "Getting the latest version of $($mod[0].name)"
$mod = $mod | Sort-Object -Property Version -Descending | Select-Object -First 1
}

Write-Verbose "Using version $($mod.version)"

$cmds = @()
Write-Verbose "Getting exported functions"
$cmds += $mod.ExportedFunctions.keys | Get-Command
Write-Verbose "Getting exported cmdlets"
$cmds += $mod.ExportedCmdlets.keys | 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).synopsis.trim()
Type = $cmd.CommandType
Version = $cmd.version
Help = $cmd.HelpUri
ModuleName = $mod.name
Compatible = $mod.CompatiblePSEditions
PSVersion = $mod.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
}
}
} #foreach cmd

#display results sorted by name for better formatting
$out | Sort-Object -Property Name
}
End {
Write-Verbose "Ending $($MyInvocation.MyCommand)"
}
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 |
(Get-Module -Name "$wordtoComplete*").name |
ForEach-Object {
# completion text,listitem text,result type,Tooltip
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
}
}