PowerShell Pipeline

A Look at PowerShell History

There are times when we look back on our PowerShell history to find a command that we had run so we can run it again or we just wanted to know what we had run to see if there is anything to pull and save for later on.

 Get-History is a powerful command that allows us to view all of the commands that we have run in our current session ... up to a certain limit (more on that later).

What I will cover today includes using our PowerShell history to help with more than just finding old commands run as well as other tidbits of information to make your history work for you.

Setting a History Limit
In PowerShell, there is an automatic variable called $MaximumHistoryCount which tells PowerShell how much of your history to keep in a session. How do I know this? By looking at the description on the variable itself.

[Click on image for larger view.]  Figure 1. A look at the MaximumHistoryCount variable.

We can set the value from anything between 1 and 32767 for PowerShell to keep in the current session. I know this by looking deeper in the variable attributes and noting the Min and Max values in the ValidateRangeAttribute.

[Click on image for larger view.]  Figure 2. Viewing the min and max values supported for MaximumHistoryCount.

How do you change this? Simply just assign a new value and you are ready to go.

$MaximumHistoryCount = 500 

Add Execution Time To Get History
If you look closely at the object from Get-History, you will see that it has a StartExecutionTime and an EndExecutionTime. Using both of these properties gives you a great look into how long that particular command took to complete. An example of this is shown below:

Get-History | 
Select-Object -Property Id, CommandLine, @{L='ExecutionTime';E={($_.EndExecutionTime-$_.StartExecutionTime)}}
[Click on image for larger view.]  Figure 3. Adding the ExecutionTime property.

Of course, if you really wanted it done for you, you can simply use a proxy function for Get-History or update the type and format file that covers this object so you have it display the value up front. What I did is combine both of these approaches by not only providing the ExecutionTime property but also updates the format data for the new type so it displays the Id, Commandline and the ExecutionTime in the output. I also added an extra feature that lets you filter what is displayed via the –CommandLine parameter which supports wildcards.

My function, Get-History2 which is available to download here also has an alias of 'h' to view the history of your PowerShell session and provides the execution time.

Get-History2 
[Click on image for larger view.]  Figure 4. Using Get-History2 to view the ExecutionTime.

 

Get-History2 -CommandLine  *Select*
[Click on image for larger view.]  Figure 5. Filtering history by the commandline property.

Persistent History
The last thing that I will show you is how you can keep the history that you had in a previous PowerShell session using nothing more than a couple of commands that you can keep in your PowerShell profile.

Using Get-History and Export-CliXml, we can save our history off as an XML file which keeps all of the object depth so we can make use of it later on.

$HistoryPath = 'C:\users\boepr\Documents\WindowsPowerShell\History'
If (-NOT (Test-Path $HistoryPath)) {
$null = New-Item -Path $HistoryPath -ItemType Directory
}
Get-History | Export-Clixml -Path "$HistoryPath\History.xml"

Now, this works great as a manual way to save off the history, but I want something that will save the history whenever the console exits so that way we have our history for the next session. To do that, I will make use of Register-EngineEvent which will let me perform an action whenever the console exits.

Register-EngineEvent -SourceIdentifier powershell.exiting  -SupportEvent -Action  {  
Get-History | Select-Object -Last 100 | Export-Clixml -Path "$HistoryPath\History.xml"
}

Note that I specify that this is a SupportEvent which means that if I were to use Get-Job, nothing would actually show up. Now whenever I close PowerShell, the last 100 objects in my PowerShell history will be saved. This is only the first part of what I need in my profile though. Saving off the history is one thing, but making it available for my next PowerShell session is another.

To accomplish this, I add the following line to my PowerShell profile which will take the contents of the XML file and add the history objects into my current history so it is available to use.

If (Test-Path  $HistoryPath) {
  Add-History  -InputObject (Import-Clixml  "$HistoryPath\History.xml")
}

It's really nothing special, but using Add-History will take the contents of the XML file (with the help of Import-CliXml) and load it into the current history. This is a great way to ensure that you have some sort of history of previous sessions to fall back on

The full code that you would put in your PowerShell profile is here:

$HistoryPath = 'C:\users\boepr\Documents\WindowsPowerShell\History'
If (Test-Path "$HistoryPath\History.xml") {
Add-History -InputObject (Import-Clixml "$HistoryPath\History.xml")
} ElseIf (-NOT (Test-Path $HistoryPath)) {
$null = New-Item -Path $HistoryPath -ItemType Directory
}

Register-EngineEvent -SourceIdentifier powershell.exiting -SupportEvent -Action { 
Get-History | Select-Object -Last 100 | Export-Clixml -Path "$HistoryPath\History.xml"
}

That wraps up this article on working with PowerShell history and hopefully this provides a couple of useful techniques that you can use!

About the Author

Boe Prox is a Microsoft MVP in Windows PowerShell and a Senior Windows System Administrator. He has worked in the IT field since 2003, and he supports a variety of different platforms. He is a contributing author in PowerShell Deep Dives with chapters about WSUS and TCP communication. He is a moderator on the Hey, Scripting Guy! forum, and he has been a judge for the Scripting Games. He has presented talks on the topics of WSUS and PowerShell as well as runspaces to PowerShell user groups. He is an Honorary Scripting Guy, and he has submitted a number of posts as a to Microsoft's Hey, Scripting Guy! He also has a number of open source projects available on Codeplex and GitHub. His personal blog is at http://learn-powershell.net.

comments powered by Disqus
Most   Popular