|
using namespace Microsoft.PowerShell.Commands
|
|
using namespace System.Collections.Generic
|
|
using namespace System.IO
|
|
|
|
$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
|
|
}
|
|
}
|