TM-SessionHistory.psm1
using namespace Microsoft.PowerShell.Commands using namespace System.Collections.Generic $script:IsAdmin = Test-Admin # Create the HistoryPath variable for use within the functions. $script:HistoryPath = Join-Path -Path (Get-ShellPath).FullName -ChildPath 'history.log' # Create a SessionGuid variable containing a guid to identify the session by. Used by the SessionHistory commands. $script:SessionGuid = (New-Guid).Guid # Set local PSVersion variable for use within the functions. $script:PSVersion = Get-PSVersionString class SessionHistory { <# .SYNOPSIS This class represents a PowerShell session history item. .DESCRIPTION A SessionHistory object encapsulates the properties related to a single command executed in a PowerShell session. It includes distinguishing information about the current powershell session by pulling profile script variables ($script:PSVersion, $script:SessionGuid, $script:IsAdmin) and gathering current runtime state and history information. This class, combined with the Get-SessionHistory, Set-SessionHistory, and Remove-SessionHistory Commands facilitates easy and safe documentation of a sessions command history. Session History values are saved to the $script:HistoryPath by the Set-SessionHistory function which is called during prompt execution. The Get-SessionHistory command facilitates easy extraction of commands from a given session history. This can be used after an iterative design/testing session to pull out specific commands for documentation purposes. The Remove-SessionHistory command provides options for removing specific commands, or entire session histories from the $script:HistoryPath in case you accidentally paste a password into your session. #> $Client $Guid $Admin $Provider $CurrentPath $ExecutionTime $ExecutionDuration $Command SessionHistory([HistoryInfo]$HistoryInfo) { $this.Client = $script:PSVersion $this.Guid = $script:SessionGuid $this.Admin = $script:IsAdmin $this.Provider = $pwd.Provider.Name $this.CurrentPath = (Get-CurrentPath) $this.ExecutionTime = $HistoryInfo.StartExecutionTime.ToString('yyyy-MM-ddTHH:mm:ss K') $this.ExecutionDuration = (Get-LastExecutionDuration $HistoryInfo) $this.Command = $HistoryInfo.CommandLine } SessionHistory([PSCustomObject]$CustomObject) { $this.Client = $CustomObject.Client $this.Guid = $CustomObject.Guid $this.Admin = $CustomObject.Admin $this.Provider = $CustomObject.Provider $this.CurrentPath = $CustomObject.CurrentPath $this.ExecutionTime = $CustomObject.ExecutionTime $this.ExecutionDuration = $CustomObject.ExecutionDuration $this.Command = $CustomObject.Command } [boolean] Equals($otherHistory) { if ( ($null -ne $otherHistory) -and ($otherHistory.GetType().FullName -eq 'SessionHistory') -and ($this.Client -eq $otherHistory.Client) -and ($this.Guid -eq $otherHistory.Guid) -and ($this.Admin -eq $otherHistory.Admin) -and ($this.Provider -eq $otherHistory.Provider) -and ($this.CurrentPath -eq $otherHistory.CurrentPath) -and ($this.ExecutionTime -eq $otherHistory.ExecutionTime) -and ($this.ExecutionDuration -eq $otherHistory.ExecutionDuration) -and ($this.Command -eq $otherHistory.Command) ) { return $true } else { return $false } } [string] ToString() { # This prevents "The script failed due to call depth overflow." on Windows PowerShell. # This was "return ($this | ConvertTo-Json -Compress)" but that had depth issues. return ( [PsCustomObject]@{ Client = $this.Client Guid = $this.Guid Admin = $this.Admin Provider = $this.Provider CurrentPath = $this.CurrentPath ExecutionTime = $this.ExecutionTime ExecutionDuration = $this.ExecutionDuration Command = $this.Command } | ConvertTo-Json -Compress ) } } function Get-SessionHistory { <# .SYNOPSIS Retrieves PowerShell session history. .DESCRIPTION Get-SessionHistory is a function that retrieves the history of commands executed in a previous PowerShell or Bash shell session. To get this functionality in your bash sessions you will also need to edit your .bashrc file as shown in GISTLINKGOESHERE. The SessionHistory items are retrieved from a script defined JSON file ($script:HistoryPath). The function can retrieve the history associated with a specific session by GUID or all available history entries from the file. .PARAMETER Guid The unique identifier associated with a specific PowerShell session. If specified, only the history from this session is retrieved. By Default this is populated with the profile script defined SessionGuid. .PARAMETER All If this switch is used then all available session history is returned. .OUTPUTS List[SessionHistory] - The function returns a list of SessionHistory objects. .EXAMPLE # The retrieved SessionHistory items can be parsed to easily select commands for reuse from your current session. Get-SessionHistory | Select-Object -ExpandProperty Command .EXAMPLE # Retrieve the commands from the 5 latest sessions. Get-SessionHistory -All | Select-Object -ExpandProperty Guid -Unique | Select-Object -Last 5 | %{ Write-Host "`n`nGuid: $_" Get-SessionHistory -Guid $_ | Select-Object -ExpandProperty Command } #> [CmdletBinding()] [CmdletBinding(DefaultParameterSetName = 'Guid')] [OutputType([List[SessionHistory]])] param( [Parameter( Mandatory = $false, ParameterSetName = 'Guid', ValueFromPipeline, ValueFromPipelineByPropertyName )] [string]$Guid = $script:SessionGuid, [Parameter( Mandatory, ParameterSetName = 'All' )] [switch]$All ) $SessionHistory = [List[SessionHistory]]::New() $HistoryContent = Get-Content -Path $script:HistoryPath | ConvertFrom-Json foreach ($item in $HistoryContent) { if (($PSCmdlet.ParameterSetName -eq 'All') -or ($item.Guid -eq $Guid)) { $SessionHistory.Add([SessionHistory]::New($item)) } } return $SessionHistory } function Remove-SessionHistory { <# .SYNOPSIS Deletes specified entries from the PowerShell session history. .DESCRIPTION The Remove-SessionHistory function can either delete all entries associated with a specific session GUID or a single specified history item from the session history stored in the JSON history file ($script:HistoryPath). This function helps enhance the security of your scripting environment by providing the ability to remove commands from the session history that may have exposed sensitive information, such as passwords. Please note that this function does not replace any session history information stored in PowerShell's built-in history location, which is accessible via (Get-PSReadLineOption).HistorySavePath. When removing sensitive information users should also manage their PSReadLine history from that location as well. .PARAMETER Guid Specifies the unique session GUID to remove history entries for. .PARAMETER HistoryItem Specifies a particular SessionHistory item to remove from the $script:HistoryPath file. .EXAMPLE # Remove the previously run command from the session history. Get-SessionHistory | Select-Object -Last 1 | Remove-SessionHistory #> [CmdletBinding()] [CmdletBinding(DefaultParameterSetName = 'HistoryItem')] [OutputType([Void])] param( [Parameter( Mandatory, ParameterSetName = 'Guid', ValueFromPipelineByPropertyName )] [string]$Guid, [Parameter( Mandatory, ParameterSetName = 'HistoryItem', ValueFromPipeline, ValueFromPipelineByPropertyName )] [SessionHistory]$HistoryItem ) $OutputHistory = [List[SessionHistory]]::New() $SessionHistory = Get-SessionHistory -All foreach ($item in $SessionHistory) { if ( (($PSCmdlet.ParameterSetName -eq 'Guid') -and ($item.Guid -ine $Guid)) -or (($PSCmdlet.ParameterSetName -eq 'HistoryItem') -and ($HistoryItem.Equals($HistoryValue) -eq $false)) ) { $OutputHistory.Add($item) } } $OutputContent = foreach ($element in $OutputHistory) { $element.ToString() } $OutputContent | Out-File $script:HistoryPath -Force } function Set-SessionHistory { <# .SYNOPSIS This function is run automatically during prompt execution. It records details about the last executed command's and appends them to the $script:HistoryPath (session history file). .DESCRIPTION Set-SessionHistory is used to capture the details of the last executed command in a PowerShell session and append them as a new SessionHistory entry to a dedicated JSON file, identified by the $script:HistoryPath variable. If no HistoryInfo information is provided, then the function captures the details of the most recently run command. If no $CommandHistory can be found then the function does nothing at all. This function is run at the end of the prompt, so if you close out your powershell session while a command is executing the commands history will not be saved. This function is run in addition to any functionality you have configured via PSReadLine. .PARAMETER CommandHistory The HistoryInfo object for an command executed in a PowerShell session. If not specified, the function will automatically retrieve the most recent command history (if any exists). #> [CmdletBinding()] [OutputType([System.Void])] param( [Parameter(Mandatory = $false)] [HistoryInfo]$CommandHistory ) $ErrorActionPreference = 'Ignore' if ($null -eq $CommandHistory) { $CommandHistory = Get-History -Count 1 } if (($null -ne $CommandHistory) -and ([string]::IsNullOrWhiteSpace($script:HistoryPath) -eq $false)) { [SessionHistory]::New($CommandHistory).ToString() | Out-File $script:HistoryPath -Append -Encoding UTF8 } } |