IntelliTect.PSRestore.psm1
function script:Get-HistoryCsvHeader() { $historyHeader = @() $historyHeader += '#TYPE Microsoft.PowerShell.Commands.HistoryInfo' $historyHeader += '"Id","CommandLine","ExecutionStatus","StartExecutionTime","EndExecutionTime"' return $historyHeader.Clone(); } function script:Get-PowerShellHistoryFileName { $currentTabTitle = $null; if(Test-path variable:psise) { $currentTabTitle = ".$($psise.CurrentPowerShellTab.DisplayName)" } return ([io.path]::ChangeExtension( $profile , "$currentTabTitle.CommandHistory.csv")) } function Import-PowerShellHistory { <# .SYNOPSIS Imports PowerShell history from the given .csv file into the current session. .EXAMPLE Import-PowerShellHistory .PARAMETER HistoryLogFile The file to import history from. This file is generated with Export-PowerShellLastCommand. Defaults to a file named after the current tab (ISE) or window name (PowerShell) .NOTES In PowerShell ISE, this does not import commands to the buffer accessed with the up-arrow key. To access these imported commands, type # and press tab, or run Get-History #> [CmdletBinding()] param( [string] $historyLogFile = (Get-PowerShellHistoryFileName), [switch] $passthru ) # See http://jamesone111.wordpress.com/2012/01/28/adding-persistent-history-to-powershell/ to save history across sessions # For more history stuff check out http://orsontyrell.blogspot.ca/2013/11/true-powershell-command-history.html Write-Host "PowerShellRestore: Restoring history: $historyLogFile" $MaximumHistoryCount = 2048; $truncateLogLines = 1000 if (Test-Path $historyLogFile) { #TODO: Change so that Select -Unique excludes the ID number and DateTime stamps which currently makes all items unique. $csvImport = Import-Csv $historyLogFile if($csvImport -and $csvImport.Count -gt 0) { $history = $csvImport[-([math]::Min($csvImport.Length, $truncateLogLines))..-1] # $history += $historyLogFileContents[-([math]::Min($historyLogFileContents.Length, $truncateLogLines))..-1] | where {$_ -match '^"\d+"'} | select -Unique $history | Add-History -Passthru:$passthru # -errorAction SilentlyContinue } } } Function Export-PowerShellLastCommand { <# .SYNOPSIS Appends the last run command in the current session to the given .csv file. .EXAMPLE Export-PowerShellLastCommand .PARAMETER HistoryLogFile The file to export history to. This file is consumed by Import-PowerShellHistory. Defaults to a file named after the current tab (ISE) or window name (PowerShell) #> [CmdletBinding()] param( [string] $historyLogFile = (Get-PowerShellHistoryFileName) ) [int] $id = 0; $history = @(get-history -count 2); if($history) { if($history.Count -eq 2) { if($history[0].CommandLine -ne $history[1].CommandLine) { #Save the last command if it was different from the previous one. $history[1] | Export-Csv $historyLogFile -append -confirm:$false $id = $history[1].Id+1 } } elseif($history.Count -eq 1) { $history[0] | Export-Csv $historyLogFile -append -confirm:$false $id = $history[0].Id+1 } } return $id } Function script:Get-WorkingDirectoryLogFileName { return ([io.path]::ChangeExtension( $profile , "$($psise.CurrentPowerShellTab.DisplayName).WorkingDirectory.txt")) } $script:lastSavedPath = $null Function Export-PowerShellISEWorkingDirectory { <# .SYNOPSIS Saves the given path to the given file if it has changed since last save. Only works in PowerShell ISE. .EXAMPLE Export-PowerShellISEWorkingDirectory .PARAMETER WorkingDirectoryLogFile The file to export the working directory to. Defaults to a file named after the current tab. .PARAMETER Path The path to export to the file. Defaults to $pwd #> [CmdletBinding()] param( [string] $workingDirectoryLogFile = $null, [string] $Path = $pwd.Path ) if (Test-Path variable:psise) { if ($script:lastSavedPath -ne $Path){ if (!$workingDirectoryLogFile){ $workingDirectoryLogFile = Get-WorkingDirectoryLogFileName } $Path > $workingDirectoryLogFile $script:lastSavedPath = $Path } } } Function Import-PowerShellISEWorkingDirectory { <# .SYNOPSIS Sets the working directory to the path contained in the given file. Only works in PowerShell ISE. .EXAMPLE Import-PowerShellISEWorkingDirectory .PARAMETER WorkingDirectoryLogFile The file to import the working directory from. Defaults to a file named after the current tab. #> [CmdletBinding()] param( [string] $workingDirectoryLogFile ) if (Test-Path variable:psise) { if (!$workingDirectoryLogFile){ $workingDirectoryLogFile = Get-WorkingDirectoryLogFileName } if (Test-Path $workingDirectoryLogFile){ $path = Get-Content $workingDirectoryLogFile Set-Location $path -ErrorAction Continue $script:lastSavedPath = $path } } } Function Install-PSRestore { <# .SYNOPSIS Imports the last saved history and working directory, and injects commands into Prompt to automatically save these for future sessions. .DESCRIPTION Recommended usage of this function is to place it at the bottom of your PowerShell profile. To do this automatically to your CurrentUserAllHosts profile, call this cmdlet with the -Persist flag, and then restart your PowerShell session. If you have a custom Prompt function, make sure to invoke Install-PSRestore after it is defined. Install-PSRestore will inject commands into your custom prompt. If your Prompt function is defined in profiles other than the one that Install-PSRestore is called in, be aware of the order in which profiles are ran - you may accidentally overwrite Install-PSRestore's injections. .EXAMPLE Install-PSRestore .PARAMETER Persist If this flag is set, Install-PSRestore will be added to your CurrentUserAllHosts profile. .LINKS https://technet.microsoft.com/en-us/magazine/2008.10.windowspowershell.aspx .NOTES If you are running this command in your profile, and you have a custom prompt function, make sure to run this after your custom prompt has been defined. This function adds the following two lines to the top of your prompt: Export-PowerShellISEWorkingDirectory $historyId = Export-PowerShellLastCommand #> [CmdletBinding()] param( [switch] $Persist ) if ($Persist){ $path = $PROFILE.CurrentUserAllHosts if (!(Test-Path $path)){ New-Item $path -ItemType file -Force } if (Select-String -Path $path -Pattern "Install-PSRestore"){ throw "CurrentUserAllHosts profile seems to already contain Install-PSRestore. You shouldn't put it there twice." } else { Add-Content -Path $path @" # Autogenerated by 'Install-PSRestore -Persist': Import-Module Intellitect.PSRestore -ErrorAction SilentlyContinue if (Get-Module IntelliTect.PSRestore) { Install-PSRestore } else { Write-Warning "Module Intellitect.PSRestore not found. Skipping Install-PSRestore from `$(`$PSCommandPath)" } "@ } } else { try { Import-PowerShellHistory Import-PowerShellISEWorkingDirectory } catch { Write-Error $_ Write-Host "Error restoring state: $_" } Invoke-Expression -Command @" Function global:Prompt { Export-PowerShellISEWorkingDirectory `$historyId = Export-PowerShellLastCommand $((Get-Command 'Prompt').Definition) } "@ } } |