How to Search PowerShell Command History Across All Sessions in Windows 10


3 views

Many PowerShell users encounter this frustrating scenario: you can scroll through past commands from multiple sessions using the up arrow key, but Get-History only shows commands from your current session. Here's why:

PS C:\> Get-History

  Id CommandLine
  -- -----------
   1 Get-History
   2 Get-Process

Windows PowerShell (5.1) maintains command history in two locations:

  • Session history: Temporary memory storage (accessed via Get-History)
  • Console history: Persistent storage in the registry (accessed via arrow keys)

To retrieve your complete command history, including from previous sessions, use this registry query:

function Get-FullPSHistory {
    $historyPath = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU'
    (Get-ItemProperty -Path $historyPath).MRUList | ForEach-Object {
        [PSCustomObject]@{
            Command = (Get-ItemProperty -Path $historyPath).$_
            Order = $_
        }
    } | Sort-Object Order | Format-Table -AutoSize
}

For better long-term history management, add this to your PowerShell profile ($PROFILE):

$global:PSHistoryPath = "$env:USERPROFILE\PSHistory.log"
function Save-PSHistory {
    $history = Get-History -Count 1000
    $history | Export-Clixml -Path $global:PSHistoryPath
}
Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action { Save-PSHistory } | Out-Null
if (Test-Path $global:PSHistoryPath) {
    Import-Clixml $global:PSHistoryPath | Add-History
}

Combine these approaches for powerful history searching:

function Search-PSHistory {
    param(
        [string]$Filter
    )
    # Get current session history
    $current = Get-History | Where-Object { $_.CommandLine -like "*$Filter*" }
    
    # Get saved history
    $saved = if (Test-Path $global:PSHistoryPath) {
        Import-Clixml $global:PSHistoryPath | Where-Object { $_.CommandLine -like "*$Filter*" }
    }
    
    # Combine and deduplicate
    ($current + $saved) | Sort-Object -Property Id -Unique
}

Consider these PowerShell modules for enhanced history management:

  • PSReadLine (built into PowerShell 5.1+): Get-PSReadLineOption
  • PSHistory: Provides cross-session history with search capabilities

As a long-time PowerShell user, I've frequently encountered the limitation where Get-History only shows commands from the current session. This becomes particularly frustrating when you need to:

  • Recover complex commands from previous work sessions
  • Find and re-run pipeline operations
  • Audit historical system administration tasks

In PowerShell 5.1 (the default version in Windows 10), command history works like this:

# Current session only shows 32 commands by default
$MaximumHistoryCount = 32
Get-History | Measure-Object # Counts current session entries

Here are three practical approaches to maintain command history across sessions:

1. Using PSReadLine Module (Recommended for PS 5.1+)

# Install if not present
if (-not (Get-Module -Name PSReadLine)) {
    Install-Module PSReadLine -Force
}

# Configure persistent history
Set-PSReadLineOption -HistorySaveStyle SaveAtExit -HistorySavePath "$HOME\ps_history.txt"

# Search history like this:
Get-Content "$HOME\ps_history.txt" | Select-String "docker cp"

2. Custom History Function with Export/Import

function Save-History {
    param(
        [string]$Path = "$env:USERPROFILE\Documents\PowerShell\persistent_history.csv"
    )
    Get-History | Export-Csv -Path $Path -NoTypeInformation
}

function Get-PersistentHistory {
    param(
        [string]$Path = "$env:USERPROFILE\Documents\PowerShell\persistent_history.csv",
        [string]$Filter = "*"
    )
    if (Test-Path $Path) {
        Import-Csv $Path | Where-Object { $_.CommandLine -like $Filter }
    }
}

# Add to profile to run at exit
$ExecutionContext.SessionState.InvokeCommand.InvokeScript($false, {
    Register-EngineEvent -SourceIdentifier PowerShell.Exiting -Action {
        Save-History
    }
}, $null, $null)

3. Leveraging the Windows Event Log

# Enable PowerShell transcription (run as admin)
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "EnableTranscripting" -Value 1

# Then search transcripts (example for last 7 days)
$startDate = (Get-Date).AddDays(-7)
Get-ChildItem "$HOME\Documents" -Filter "PowerShell_transcript*" | 
    Select-String "docker cp" | 
    Where-Object { $_.Path -like "*_$($startDate.ToString('yyyyMMdd'))*" }

Combine these approaches into a reusable function:

function Search-PSHistory {
    param(
        [Parameter(Mandatory)]
        [string]$Pattern,
        [int]$Days = 30,
        [switch]$IncludeCurrentSession
    )
    
    $results = @()
    
    # Current session
    if ($IncludeCurrentSession) {
        $results += Get-History | Where-Object { $_.CommandLine -match $Pattern }
    }
    
    # PSReadLine history
    if (Test-Path "$HOME\ps_history.txt") {
        $results += Get-Content "$HOME\ps_history.txt" | 
            Where-Object { $_ -match $Pattern } |
            ForEach-Object {
                [PSCustomObject]@{
                    Id          = [guid]::NewGuid()
                    CommandLine = $_
                    StartTime   = $null
                    EndTime     = $null
                }
            }
    }
    
    # Custom history file
    if (Test-Path "$env:USERPROFILE\Documents\PowerShell\persistent_history.csv") {
        $results += Import-Csv "$env:USERPROFILE\Documents\PowerShell\persistent_history.csv" | 
            Where-Object { $_.CommandLine -match $Pattern }
    }
    
    # Return unique results sorted by date (when available)
    $results | Sort-Object { try { [datetime]$_.StartTime } catch { [datetime]::MinValue } } -Descending
}

Example usage:

# Find all docker commands from any available history source
Search-PSHistory -Pattern "docker" -IncludeCurrentSession

# Search last 14 days for container operations
Search-PSHistory -Pattern "container|docker" -Days 14