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.ps1
let’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.