powershellhistory

PowerShell's Clear-History doesn't clear history


Recently I had to run a command that unfortunately required me to type a password right on the command line.

Afterwards, I cleared my screen with "Clear", but also wanted to clear the command history so the offending command wouldn't show up in the session history. Unfortunately, the Clear-History cmdlet doesn't seem to actually do what its documentation claims - running Clear-History doesn't seem to have any impact on the session history whatsoever.

I can still see previous commands in the pop-up history menu, and scroll through old commands by pressing the up key. Here's a screengrab demonstrating the problem:

PowerShell clear history failure

I've verified with Get-Command that Clear-History is indeed executing the expected built-in PowerShell cmdlet.

I've tried a few variations, such as "Clear-History -count 10 -newest", all failing to show any effect. When I specify an exact history ID, such as "Clear-History -id 3", I receive an error like this:

Clear-History : Cannot locate history for Id 3.

Even if I can see command #3 on the screen.


Solution

  • tl;dr


    To complement CB.'s helpful answer and JVimes's helpful answer:


    The following advanced function bundles all commands necessary to clear the command history (both for PowerShell itself and the console), both for doskey-style and PSReadline-module PowerShell console windows:

    Note:

    <#
    # .SYNOPSIS
    #  Clears the command history, including the saved-to-file history, if applicable.
    #>
    function Clear-SavedHistory {
      [CmdletBinding(ConfirmImpact='High', SupportsShouldProcess)]
      param(    
      )
    
      # Debugging: For testing you can simulate not having PSReadline loaded with
      #            Remove-Module PSReadline -Force
      $havePSReadline = ($null -ne (Get-Module -EA SilentlyContinue PSReadline))
    
      Write-Verbose "PSReadline present: $havePSReadline"
    
      $target = if ($havePSReadline) { "entire command history, including from previous sessions" } else { "command history" } 
    
      if (-not $pscmdlet.ShouldProcess($target))
      {
            return
      }
    
      if ($havePSReadline) {
        
        Clear-Host
    
        # Remove PSReadline's saved-history file.
        if (Test-Path (Get-PSReadlineOption).HistorySavePath) { 
          # Abort, if the file for some reason cannot be removed.
          Remove-Item -EA Stop (Get-PSReadlineOption).HistorySavePath 
          # To be safe, we recreate the file (empty). 
          $null = New-Item -Type File -Path (Get-PSReadlineOption).HistorySavePath
        }
    
        # Clear PowerShell's own history 
        Clear-History
    
        # Clear PSReadline's *session* history.
        # General caveat (doesn't apply here, because we're removing the saved-history file):
        #   * By default (-HistorySaveStyle SaveIncrementally), if you use
        #    [Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory(), any sensitive
        #    commands *have already been saved to the history*, so they'll *reappear in the next session*. 
        #   * Placing `Set-PSReadlineOption -HistorySaveStyle SaveAtExit` in your profile 
        #     SHOULD help that, but as of PSReadline v1.2, this option is BROKEN (saves nothing). 
        [Microsoft.PowerShell.PSConsoleReadLine]::ClearHistory()
    
      } else { # Without PSReadline, we only have a *session* history.
    
        Clear-Host
        
        # Clear the doskey library's buffer, used pre-PSReadline. 
        # !! Unfortunately, this requires sending key combination Alt+F7.
        # Thanks, https://stackoverflow.com/a/13257933/45375
        $null = [system.reflection.assembly]::loadwithpartialname("System.Windows.Forms")
        [System.Windows.Forms.SendKeys]::Sendwait('%{F7 2}')
    
        # Clear PowerShell's own history 
        Clear-History
    
      }
    
    }