Advanced Windows PowerShell Scripting Video Training

Advanced Windows PowerShell Scripting Video Training
Advanced Windows PowerShell Scripting Video Training

Friday, October 5, 2012

Search for key words in PowerShell help files

One of my students from a PowerShell class a few weeks back was wondering if he could search PowerShell help files for key words and have those words highlighted in the help file.  This week I decided to tackle this one and here are the results.
Below is a screen shot of the function Search-Help
image
Please take the time to read through the help file.  The code below is presented as a function that can be turned into a module and added to your PowerShell profile.
This code is provided as is and without warranty or support.

Function Search-Help
{
[CmdletBinding(HelpUri = 'http://get-help-jason-yoder.blogspot.com/2012/10/search-help.html')]

Param(
    # Parameter $Cmdlet
    # The name of the parameter that you want to get help on.
    [Parameter(Mandatory=$true)]$Cmdlet,

    # Parameter $Words
    # The name of the parameter that you want to get help on.   
    [Parameter(Mandatory=$true)][String[]]$Words,

    # Parameter $Detailed
    # Parse the detailed help file of the cmdlet.
    [Switch]$Detailed,

    # Parameter $Detailed
    # Parse the full help file of the cmdlet.
    [Switch]$Full,

    # Parameter $MoreHighlight
    # Changes the highlighted text to a different
    # color set to make the search items stand out
    # better.
    [Switch]$MoreHighlight,

    # Parameter $ExactMatch
    # Changes the default behavior of the algorithm to
    # look for an exact match as opposed to a match
    # containing the query.
    [Switch]$ExactMatch

)
  
    # Supporting Function Compare-Strings -------------------------------------
    # Send this function:
    # 1: The word to examine.
    # 2: The word you want to see if it is in the first.
    # * and ? are acceptable wild car characters.
    # This function will return $TRUE is the $TestString contains the pattern
    # from $TestWord.  This function is the default behavior of the cmdlet.
    Function Compare-Strings
    {
    Param(
        [String]$TestString,
        [String]$TestWord
    )

        # Set the Return flag data
        [Boolean] $MatchFound = $False

        # Break the $TestString into a Cahr array
        $CharArray = $TestString.ToCharArray()

        # Loop through the CharArray, adding one character to the
        # Search to see if it matches.

        # The sting that holds the value to be tested.
        $TestArray = $Null

        # Controls the inner While loop and adds characters to be tested.
        $Index = 0

        # Controls the outer while loop and determines which characters
        # from the left to start the comparison with.
        $OuterIndex = 0

        Do
        {
            $Index = $OuterIndex
            Do
            {
                # Add a character to the test string
                $TestArray += $CharArray[$Index]
                If($TestArray -like $TestWord)
                {
                    $MatchFound = $True
                }
           
                # Increment the control variable.
                $Index++
           
            } While ($Index -Lt $TestString.length)

            # Clear the TestArray
            $TestArray = $Null
           
            # Increment the control variable
            $OuterIndex++
       
        } While ($OuterIndex -lt $TestString.length)
       
        # Return the data to the calling command.
        Write-Output $MatchFound
    }
    # End Supporting Function Compare-Strings ---------------------------------

    # Supporting Function Compare-StringsExact --------------------------------
    # Send this function:
    # 1: The word to examine.
    # 2: The word you want to see if it is in the first.
    # This function will return TRUE only if there is an exact match. 
    Function Compare-StringsExact
    {
    Param(
        [String]$TestString,
        [String]$TestWord
    )
        # Set the Return flag data
        [Boolean] $MatchFound = $False
       
        If($TestString -eq $TestWord)
        {
            $MatchFound = $True
        }

        # Test to see if a match is made by removing any end punctuation.
        If($TestString -match "\w*")
        {
            If($Matches.Values -eq $TestWord)
            {
                $MatchFound = $True
            }
        }
       
        # Return the data to the calling command.
        Write-Output $MatchFound       

    }
    # End Supporting Function Compare-StringsExact ----------------------------

    # get the help file from PowerShell.
    If($Detailed)
        {$HelpData = (Get-Help $Cmdlet -Detailed) | Out-String -Stream}
    ElseIf($Full)
        {$HelpData = Get-Help $Cmdlet -Full | Out-String -Stream}
    Else
        {$HelpData = Get-Help $Cmdlet | Out-String -Stream}


    # Set a counter to keep track of how many matches are found.
    $MatchCounter = 0

    # Validate the phrase that was sent to remove
    # any solo "*" or "?".
    $SearchPhrase = @()
    $Wordss = $Words.split(",")
    $InvalidItems = @()
    Foreach ($Item in $Wordss)
    {
        If (($Item -ne "*") -and ($Item -ne "?") -and (($Item.ToCharArray())[0] -ne "*") -and (($Item.ToCharArray())[0] -ne "?"))
        {
            $SearchPhrase += $Item
        }
        Else
        {
            $InvalidItems += $Item
        }
    }
    
    # Cycle through each line of the help file.   
    Foreach ($Item in $HelpData)
    {

        # Split each line into its individual words.           
        $StringData = $Item.Split()
       
        # Cycle through every word in the current help file line.
        ForEach ($DataItem in $StringData)
        {
            # Set this flag to $True is a match is found.
            $Found = $False
           
            # Cycle through each searchword.
            foreach ($Item in $SearchPhrase)
            {
                # Use the correct function depending on if the $ExactMatch flag is set.
                If ($ExactMatch)
                {
                   $ReturnedMatch = Compare-StringsExact $DataItem $Item
                }
                Else {$ReturnedMatch = Compare-Strings $DataItem $Item}
           
                If ($ReturnedMatch){$Found = $True}
            }
          
                # If the $Found flag is set to $True, then display the word
                # in highlighted text.  If not, display the word using the
                # current color settings in the shell.
                If ($Found)
                {
                    If (-Not $MoreHighlight)
                    {
                        Write-Host "$DataItem" -ForegroundColor Magenta -BackgroundColor DarkBlue -NoNewline
                        Write-Host " " -NoNewline
                    }
                    Else
                    {
                        Write-Host "$DataItem" -ForegroundColor Green -BackgroundColor DarkGreen -NoNewline
                        Write-Host " " -NoNewline
                    }
                    # Incriment the $MatchCounter.
                    $MatchCounter++
                }
                Else
                {
                    Write-Host "$DataItem " -NoNewline
                }
           
        }
        # This adds a carriage return to the line to ensure the output resembles
        # the original help file as much as possible.
        Write-Host ""
    }

    # Write an extra line of data to the end of the help file to let the user
    # know if a match was found.
    Write-Host "-- Search Results: -------------------------------------------------------------"
    If ($MatchCounter -gt 0)
    {
        Write-Host "Your search returned " -NoNewline
        Write-Host "$MatchCounter" -ForegroundColor Green -BackgroundColor DarkBlue  -NoNewline
        Write-Host " matches."
        Write-Host "Items searched for:"
        foreach ($Item in $SearchPhrase)
        {
            Write-Host $Item -ForegroundColor Green -BackgroundColor DarkBlue
        }
        If($InvalidItems.count -gt 0)
        {
            Write-Host "Invalid search items removed from the query:"
            foreach ($Item in $InvalidItems)
            {
                Write-Host $Item -ForegroundColor Red -BackgroundColor DarkBLue
            }
        }
    }
    Else
    {
        Write-Host "No matches were found."
    }
<#
.SYNOPSIS
Searches PowerShell help files for specific words.

.DESCRIPTION
Searches through PowerShell help files for words and highlights those words in the actual help files. 
The default setting for this cmdlet is to search for the pattern specified in the WORDS parameter in each word of the help file.

.PARAMETER Cmdlet
The cmdlet or About file that you want to search for specific words.

.PARAMETER Words
Comma separated list of words that you want to search for.  The words can contain * and ? characters but cannot start with a * or ? character.

.PARAMETER Detailed
Searches the cmdlets detailed help file.

.PARAMETER Full
Searches the cmdlets full help file.

.PARAMETER MoreHighlight
Displays the queried words in a higher contrast color scheme which may make the output more readable to some users.

.PARAMETER ExactMatch
This will change the pattern recognition to an exact match (not case sensitive).  Wildcard characters are not accepted.

.EXAMPLE
Search-Help Get-Date -Words Date

Returns the standard help file for the cmdlet Get-Date and highlights all words that match or contains "Date".

.EXAMPLE
Search-Help Get-Process P*ess, more, t?pe -MoreHighlight

Returns the standard help file for the cmdlet Get-Date and highlights all words that match or contains "Date" as well as "P*ess" and "T?py"
The "*" character is a wild card character that allows for multiple characters to exists in its place.
The "?" character is a wild card character that allows for a single character to exists in its place.
The highlighted words will also be returned in greater contrast.

.EXAMPLE
Search-Help About_Comparison_Operators "-Match"

Returns the help file for About_Comparison_Operators with all words matching or contains "-Match" highlighted.

.EXAMPLE
Search-Help Get-Process -detailed Process

Returns the detailed help file for the cmdlet Get-Date and highlights all words that match or contains "Date".

.EXAMPLE
Search-Help Get-Process -Words Process -ExactMatch

Returns the standard help file for Get-Process with all words that exactly match "Process" highlighted.

.NOTES
This cmdlet sends customized output to the host one line at a time.  For this reason, standard object output for PowerShell is not utilized.

.LINK
Online Version: http://get-help-jason-yoder.blogspot.com/2012/10/search-help.html
Get-Help
#>
}

No comments: