PowerShell Incognito Mode

Back in 2021 (three years ago?!), I wrote a blog post about “incognito” mode in the bash terminal. Well, I also use Windows systems nowadays, and I needed a way of disabling PowerShell’s history function temporarily.

PowerShell has two history modules. The first one is constrained within the current session, and you can see all the commands you ran during that session by running Get-History:

PS C:\Users\erics\OneDrive\Pictures> Get-History

  Id CommandLine
  -- -----------
   1 cd .\OneDrive\Pictures\
   2 ls

The other history module is saved by PSReadLine, and this one is a bit more troublesome, as it functions exactly like .bash_history – it saves your commands to a file that persists (until you get rid of Windows or delete that file). The path at which it’s saved is $env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine.

Now, by default, the situation is even worse over on PowerShell, because commands prefixed with a space is still saved to the history, unlike bash.

Thankfully, we can fix some of these annoyances ourselves by editing our profile script.

(Note: most of the code below came from this GitHub issue discussing this exact problem!)

Editing the execution policy

Because PowerShell is configured to not run any untrusted scripts by default, we need to adjust the execution policy:

Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted -Force

There are two policies: Unrestricted and Bypass. Unrestricted will at least warn you before executing scripts, while Bypass will happily run anything and everything with zero warning (sort of like what bash and Linux shells do by default with anything with the +x flag.)

Edit the profile script

Open up the profile script in your favorite editor:

notepad++ $profile

And paste in the following:

# Don't record space-prefixed commands
Set-PSReadLineOption -AddToHistoryHandler {
    param([string]$line)
    return $line.Length -gt 3 -and $line[0] -ne ' ' -and $line[0] -ne ';'
}

# Disable/enable history wrappers
function Disable-PSReadLineHistory {
    $global:PSReadLineOldHistorySaveStyle = (Get-PSReadLineOption).HistorySaveStyle
    Set-PSReadLineOption -HistorySaveStyle SaveNothing
}

function Enable-PSReadLineHistory {
    # Only change the history style if we previously saved it in `Disable-PSReadLineHistory`
    if (Test-Path variable:PSReadLineOldHistorySaveStyle) {
        Set-PSReadLineOption -HistorySaveStyle $global:PSReadLineOldHistorySaveStyle
    }
}

Now, whenever you want to disable the PowerShell history temporarily, run Disable-PSReadLineHistory. It will disable history recording for that current session.

I wish they’d just add these in as the default.

Clearing old history

If you have sensitive commands recorded into history, then you can delete them by running Clear-History and deleting the aforementioned PSReadLine’s history file.

Or, you can use this script from Stack Overflow.

comments