Get-History Modified


Notice: The following post was originally published on another website. As the post is no longer accessible, it is being republished here on tommymaynard.com. The post was originally published on April 10, 2019.


It was a couple of articles ago where I took an unused, leftover example I had sitting in a tab inside my PowerShell editor, and used it to write an article. This happens often, but usually only when they’re good examples. In this recent case, while I believe it turned out well, I used something that wasn’t overly amazing and made it worthy. I’m doing that today. Again. I think.

What I can tell you, is that the content in this second tab was small, yet complete. Its home, in fact, had been only one tab over from the function that brought us the Build In Measure-Command post, I’ve vaguely mentioned.

To prep, let’s discuss the Get-History cmdlet. It’s been around for as long as I can remember, and its purpose, as indicated by its synopsis is this: “The Get-History cmdlet gets the session history, that is, the list of commands entered during the current session.” You enter a command and the command is added to the history. This cmdlet allows you to view your previously entered command(s) later if you choose to do that. Let’s start with a few PowerShell commands.

PS> Get-Date
Wednesday, April 7, 2019 1:47:56 PM
PS> Get-Random
217097233
PS> (Get-Process | Select-Object -First 1).ProcessName
AGMService
PS> (Get-Alias -Name gci).DisplayName
gci -> Get-ChildItem

After knowing we’ve invoked these four commands, we can invoke the Get-History cmdlet to see them in succession. The Get-History default output returns two properties: Id and CommandLine.

PS> Get-History
  Id CommandLine
  -- -----------
   1 Get-Date
   2 Get-Random
   3 (Get-Process | Select-Object -First 1).ProcessName
   4 (Get-Alias -Name gci).DisplayName

You can’t tell using this output, but there are properties that aren’t shown in the default, Get-History output. In addition to the Id and CommandLine properties, there is an ExecutionStatus property, a StartExecutionTime property, and finally, an EndExecutionTime property. Here’s an example that includes them all.

PS> Get-History | Select-Object -Property *
Id                 : 1
CommandLine        : Get-Date
ExecutionStatus    : Completed
StartExecutionTime : 4/7/2019 1:50:35 PM
EndExecutionTime   : 4/7/2019 1:50:35 PM
 
Id                 : 2
CommandLine        : Get-Random
ExecutionStatus    : Completed
StartExecutionTime : 4/7/2019 1:50:37 PM
EndExecutionTime   : 4/7/2019 1:50:37 PM
 
Id                 : 3
CommandLine        : (Get-Process | Select-Object -First 1).ProcessName
ExecutionStatus    : Completed
StartExecutionTime : 4/7/2019 1:50:45 PM
EndExecutionTime   : 4/7/2019 1:50:45 PM
 
Id                 : 4
CommandLine        : (Get-Alias -Name gci).DisplayName
ExecutionStatus    : Completed
StartExecutionTime : 4/7/2019 1:51:00 PM
EndExecutionTime   : 4/7/2019 1:51:00 PM
 
Id                 : 5
CommandLine        : Get-History
ExecutionStatus    : Completed
StartExecutionTime : 4/7/2019 1:51:09 PM
EndExecutionTime   : 4/7/2019 1:51:09 PM

If you just found this out, and you thought about what I did when I first found out, then you may have realized that we can determine how long a command took to complete, if we do a little subtraction. Subtract the start time from the end time and we know the amount of time each command has taken. And that’s the little teeny chunk of code I rescued from a soon-to-be abandoned VS Code tab. I’ve included this simple function below and the modified output from above. While the TimeTaken property doesn’t really help with the previous commands we ran, as they all ended so quickly, it easily may help for long-running commands and scripts.

Function Get-History {
    $History = Microsoft.PowerShell.Core\Get-History | Select-Object -Property *
    $History | Select-Object Id,CommandLine,
        @{Name='TimeTaken';Expression={($_.EndExecutionTime) - ($_.StartExecutionTime)}}
} # End Function: Get-History.

PS> Get-History
Id CommandLine                                        TimeTaken
-- -----------                                        ---------
 1 Get-Date                                           00:00:00.0154352
 2 Get-Random                                         00:00:00
 3 (Get-Process | Select-Object -First 1).ProcessName 00:00:00.0110123
 4 (Get-Alias -Name gci).DisplayName                  00:00:00
 5 Get-History                                        00:00:00.0154351
 6 Get-History | Select-Object -Property *            00:00:00.0158662

While everyone is still paying attention, let’s assume we have a .ps1 file saved to our Desktop on Windows. Its name is sleep.ps1 and literally, all it does is sleep for 10 seconds. After we’ve run it as . .\Desktop\sleep.ps1let’s rerun our modified Get-History command. It does exactly what we would expect; it indicates that the TimeTaken property is 10 seconds.

PS> Get-History
Id CommandLine                                        TimeTaken
-- -----------                                        ---------
 1 Get-Date                                           00:00:00.0154352
 2 Get-Random                                         00:00:00
 3 (Get-Process | Select-Object -First 1).ProcessName 00:00:00.0110123
 4 (Get-Alias -Name gci).DisplayName                  00:00:00
 5. Get-History                                       00:00:00.0154351
 6. Get-History | Select-Object -Property *           00:00:00.0158662
 7. . .\Desktop\sleep.ps1                             00:00:10.0229630

That’s it. A quick and simple way to determine the time each command takes to complete. Add this function to your $PROFILE script and it’ll always run, instead of the standard, built-in Get-History cmdlet.

Leave a Reply

Your email address will not be published. Required fields are marked *