Get-PowerHistory.ps1

function Get-PowerHistory
{
    <#
    .Synopsis
        Gets commands run in the current session and any attached information.
    .Description
        The Get-PowerHistory cmdlet gets the session history, that is, the list of commands entered during the current session.
 
        It also returns any additional information related to that history item.
 
        Additional information can be traced to the history by using Trace-PowerHistory
    .Example
        Get-PowerHistory
    .Example
        Get-PowerHistory -Count 10
    .Example
        Get-PowerHistory -ID ($MyInvocation.HistoryID - 1)
    .Link
        Clear-PowerHistory
    .Link
        Trace-PowerHistory
    .Link
        Invoke-PowerHistory
 
    #>

    [CmdletBinding(DefaultParameterSetName='All')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', "", Justification = 'Functionality Most Be Global')]
    [OutputType('Power.History')]
    param(
    <#
    Specifies an array of the IDs of entries in the session history. Get-PowerHistory gets only specified entries.
 
    If you use both the Id and Count parameters in a command,
    Get-PowerHistory gets the most recent entries ending with the entry specified by the Id parameter.
    #>

    [Parameter(Position=0, ParameterSetName='ByID', ValueFromPipeline)]
    [ValidateRange(1, 9223372036854775807)]
    [long[]]
    $Id,

    <#
    Specifies the name of one or more modules. Only history entries that use a command from those modules will be returned.
    #>

    [Parameter(Mandatory,ParameterSetName='ByModule')]
    [string[]]
    $Module,

    <#
    Specifies the name of one or more commands. Only history entries that use these commands will be returned.
    #>

    [Parameter(Mandatory,ParameterSetName='ByCommand')]
    [string[]]
    $Command,

    <#
    Specifies the name of one or more variables. Only history entries that use these variables will be returned.
    #>

    [Parameter(Mandatory,ParameterSetName='ByVariable')]
    [string[]]
    $Variable,

    <#
    Specifies the name of one or more properties. Only history entries that use these properties will be returned.
    #>

    [Parameter(Mandatory,ParameterSetName='ByProperty')]
    [Alias('Properties')]
    [string[]]
    $Property,

    <#
    Specifies the number of the most recent history entries that this cmdlet gets. By, default, Get-PowerHistory gets all entries in
    the session history. If you use both the Count and Id parameters in a command, the display ends with the command that is
    specified by the Id parameter.
    #>

    [Parameter(Position=1)]
    [ValidateRange(0, 32767)]
    [int]
    $Count
    )

    begin {
        $getHistory = $ExecutionContext.SessionState.InvokeCommand.GetCommand('Get-History','Cmdlet')
        if (-not $Global:PowerHistory) {
            $Global:PowerHistory = [Collections.Generic.Dictionary[string, PSObject]]::new([StringComparer]::OrdinalIgnoreCase)
        }
    }

    process {
        if ('ByModule', 'ByCommand', 'ByVariable', 'ByProperty' -contains $PSCmdlet.ParameterSetName) {
            Sync-PowerHistory

            $ids = [Collections.Generic.List[long]]::new()
            $c = 0
            $null = :WalkPowerHistory foreach ($kv in $Global:PowerHistory.GetEnumerator()) {
                if ($PSCmdlet.ParameterSetName -eq 'ByModule') {
                    if (-not $kv.Value.Modules) { continue }
                    foreach ($mod in $kv.Value.Modules) {
                        if ($Module -contains $mod.Name) {
                            $ids.Add($kv.Key)
                            if ($Count -and ++$c -ge $count) {
                                break WalkPowerHistory
                            }
                            break
                        }
                    }
                }
                if ($PSCmdlet.ParameterSetName -eq 'ByCommand') {
                    if (-not $kv.Value.Commands) { continue }
                    foreach ($cmd in $kv.Value.Commands) {
                        if ($Command -contains $cmd) {
                            $ids.Add($kv.Key)
                            if ($Count -and ++$c -ge $count) {
                                break WalkPowerHistory
                            }
                            break
                        }
                    }
                }
                if ($PSCmdlet.ParameterSetName -eq 'ByVariable') {
                    if (-not $kv.Value.Variables) { continue }
                    foreach ($var in $kv.Value.Variables) {
                        if ($Variable -contains $var) {
                            $ids.Add($kv.Key)
                            if ($Count -and ++$c -ge $count) {
                                break WalkPowerHistory
                            }
                        }
                    }
                }

                if ($psCmdlet.ParameterSetName -eq 'ByProperty') {
                    foreach ($prop in $property) {
                        if ($null -ne $kv.Value.$prop) {
                            $ids.Add($kv.Key)
                            if ($Count -and ++$c -ge $count) {
                                break WalkPowerHistory
                            }
                        }
                    }
                }
            }
            $PSBoundParameters['ID'] = $Ids.ToArray()
            if ($Count) { # If we have a count, we've already used it,
                $PSBoundParameters.Remove('Count') # so remove it from PSBoundParameters (to make later splatting easier).
            }
        }


        #region Call Get-History
        $getHistoryParameters = @{} + $PSBoundParameters
        foreach ($k in $PSBoundParameters.Keys) {
            if (-not $getHistory.Parameters.$k) {
                $getHistoryParameters.Remove($k)
            }
        }
        $PowerShellHistoryItems = Get-History @getHistoryParameters
        #endregion Call Get-History

        #region Join Get-History with $Global:PowerHistory
        foreach ($historyItem in $PowerShellHistoryItems) {
            $historyItem.pstypenames.clear()
            $historyItem.pstypenames.add('Power.History')

            if (-not $Global:PowerHistory[$historyItem.Id]) {
                Sync-PowerHistory -ID $historyItem.ID
            }

            if ($Global:PowerHistory[$historyItem.ID] -is [Collections.IDictionary]) {
                foreach ($additionalProperty in $Global:PowerHistory[$historyItem.ID].GetEnumerator()) {
                    if (-not $historyItem.psobject.properties[$additionalProperty.Key]) {
                        $historyItem.psobject.properties.add([PSNoteProperty]::new($additionalProperty.Key, $additionalProperty.Value))
                    }
                }
            } else {
                foreach ($additionalProperty in $Global:PowerHistory[$historyItem.ID].psobject.properties) {
                    if (-not $historyItem.psobject.properties[$additionalProperty.Name]) {
                        $historyItem.psobject.properties.add([PSNoteProperty]::new($additionalProperty.Name, $additionalProperty.Value))
                    }
                }
            }

            $historyItem
        }
        #endregion Join Get-History with $Global:PowerHistory
    }

}