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