Jonny Hotchkiss
Jonny Hotchkiss

Reputation: 91

Get date/time of commands from history on windows (cmd/ps)

https://www.2daygeek.com/display-date-time-linux-bash-history-command/

Found this article which seems to show equivalent how to for linux, using HISTTIMEFORMAT environment variable,

# history
    1  2017-08-16 15:30:15 yum install -y mysql-server mysql-client
    2  2017-08-16 15:30:15 service mysqld start
    3  2017-08-16 15:30:15 sysdig proc.name=sshd

There may be a log, or a subscription, in windows event viewer that can be enabled or registered This feature may already exist in powershell...

Checked doskey /? but nothing jumps out.

❓ Is it possible to get details of when commands were executed, and what methods are available to achieve?

Upvotes: 2

Views: 1290

Answers (1)

mklement0
mklement0

Reputation: 437418

PowerShell's Get-History cmdlet (whose built-in aliases are ghy, h, and history) outputs Microsoft.PowerShell.Commands.HistoryInfo objects, whose properties you can easily select for display with Format-Table, for instance:

Get-History | Format-Table Id, StartExecutionTime, CommandLine

Sample output:

Id StartExecutionTime    CommandLine
-- ------------------    -----------
77 4/17/2023 9:59:58 AM  Get-ChildItem *.txt
78 4/17/2023 10:00:00 AM Get-Date

Get-History's default for-display formatting shows the Duration property values instead of StartExecutionTime in PowerShell (Core) 7+, and neither in Windows PowerShell.

Of course, you're free to include both Duration and StartExecutionTime.

Note:

  • As of PowerShell 7.3.4, Get-History only ever shows the current session's history, not also the persisted history maintained by the PSReadLine module - see GitHub issue #12061 for a discussion.

  • Since the solutions presented here build on Get-History, they too are effective for the current-session history only, unlike bash's history builtin.

    • Should integration with the persistent session history ever be implemented, the latter's file format would have to be extended, given that it currently stores commands only.

If you want to change the default formatting, you have two fundamental options:

  • Author a *.format.ps1xml file with the desired columns and load it with Update-FormatData -PrependPath, from your $PROFILE file.
    This is the best approach, but non-trivial, unfortunately. See below.

  • Suboptimally, but more simply, create a custom function that wraps Get-History; you may also redefine the aliases to point to your custom function (e.g., Set-Alias h Format-HistoryCustom) - again, place these definitions in your $PROFILE file:

    function Format-HistoryCustom {  
      Get-History @args |
        Format-Table Id, StartExecutionTime, CommandLine
    }
    

Adding a StartExecutionTime column to Get-History's output, via custom formatting data loaded from $PROFILE:

The following implements the first approach discussed above. Note that on Windows PowerShell a Duration column is added as well (which is present by default in PowerShell (Core) 7+).

The customized XML data used below was obtained by obtaining the current definitions as follows, followed by updating it by hand:

Get-FormatData Microsoft.PowerShell.Commands.HistoryInfo |
  Export-FormatData -IncludeScriptBlock -LiteralPath HistoryInfo.format.ps1xml

Run this once, which will place a HistoryInfo.format.ps1xml file alongside your $PROFILE file and append a command to load that file with Update-FormatData -PrependPath to $PROFILE itself.

# Make sure that the directory in which $PROFILE is located exists.
$profileDir = New-Item -Type Directory -Force (Split-Path $PROFILE)

# Create a "HistoryInfo.format.ps1xml" file next to the profile file.
$customFormatFile = 'HistoryInfo.format.ps1xml'
@'
<?xml version="1.0" encoding="utf-8"?><!-- Add a StartExecutionTime column to Get-History output, and on WinPS also a Duration column (included by default in PowerShell (Core)). --><Configuration><ViewDefinitions><View><Name>history</Name><ViewSelectedBy><TypeName>Microsoft.PowerShell.Commands.HistoryInfo</TypeName></ViewSelectedBy><TableControl><TableHeaders><TableColumnHeader><Width>4</Width><Alignment>Right</Alignment></TableColumnHeader><TableColumnHeader><Width>21</Width><Alignment>Right</Alignment></TableColumnHeader><TableColumnHeader><Label>Duration</Label><Width>12</Width><Alignment>Right</Alignment></TableColumnHeader><TableColumnHeader /></TableHeaders><TableRowEntries><TableRowEntry><TableColumnItems><TableColumnItem><PropertyName>Id</PropertyName></TableColumnItem><TableColumnItem><PropertyName>StartExecutionTime</PropertyName></TableColumnItem><TableColumnItem><ScriptBlock>
                                $duration = $_.EndExecutionTime - $_.StartExecutionTime
                                if ($duration.TotalHours -ge 10) {
                                    return "{0}:{1:mm}:{1:ss}.{1:fff}" -f [int]$duration.TotalHours, $duration
                                }
                                elseif ($duration.TotalHours -ge 1) {
                                    $formatString = "h\:mm\:ss\.fff"
                                }
                                elseif ($duration.TotalMinutes -ge 1) {
                                    $formatString = "m\:ss\.fff"
                                }
                                else {
                                    $formatString = "s\.fff"
                                }

                                $duration.ToString($formatString)
</ScriptBlock></TableColumnItem><TableColumnItem><PropertyName>CommandLine</PropertyName></TableColumnItem></TableColumnItems></TableRowEntry></TableRowEntries></TableControl></View><View><Name>history</Name><ViewSelectedBy><TypeName>Microsoft.PowerShell.Commands.HistoryInfo</TypeName></ViewSelectedBy><WideControl><WideEntries><WideEntry><WideItem><PropertyName>CommandLine</PropertyName></WideItem></WideEntry></WideEntries></WideControl></View></ViewDefinitions></Configuration>
'@ > (Join-Path $profileDir $customFormatFile)

# Append a command to the profile that loads the formatting data into every session.
@"

# Load custom formatting data for Get-History.
Update-FormatData -PrependPath "`$PSScriptRoot/$customFormatFile"
"@ | Add-Content $PROFILE

Upvotes: 2

Related Questions