History is boring.
While I don’t believe that is true (I actually find history quite fascinating), it is certainly how I would have responded if asked about history while taking it in high school. I’m not the only one who felt this way back then either. When I asked my wife for her opinion about it, she told me that it was in her history class where she learned to write upside down with her non-dominant hand.
My problem with history is the presentation of it. It can be fun and include a lot of contextual detail that is presented with zeal and that connects with the audience; or, like my high school history class, it can be presented as a timeline with boring details attached to it.
PowerShell automatically tracks the commands that you invoke in a history table that you can view at any time with the Get-History cmdlet. If you invoke Get-History (or its alias, h) after you’ve been using PowerShell for a bit, you should see results similar to the following:
That’s not entirely useless, because it shows commands that we ran earlier, but as far as presentation goes it’s pretty boring, right? Now, this is only the default format for history in PowerShell, and as with most data in PowerShell this screenshot doesn’t paint the full picture. Each entry also includes other fields that are not shown in the default format, as can be seen here:
The problem is, that’s all you get: a timeline with boring details attached to it. The ExecutionStatus property tells me whether a command completed or failed, but the usefulness of that information is very limited because a value of Failed only means the command failed with a terminating error; if a command failed with a non-terminating error, then ExecutionStatus will simply indicate that the command completed, which is not very useful knowledge to have. Start and end execution times are useful, but that means I need to do math to determine how long various commands took, or re-run the commands inside of Measure-Command. There’s no zeal behind the presentation of this information.
Fortunately, PowerShell is extensible, so I decided I should be able to do better. Here’s my view of what PowerShell history should be, as provided by HistoryPx:
HistoryPx is an open-source PowerShell module that transparently integrates into the PowerShell environment where it is loaded. You simply load the module by importing it with Import-Module into an environment running PowerShell 3.0 or later, and once it is loaded it will start tracking extended history information for every command you run. Extended history information includes the command duration, whether or not the command was successful, any output returned by the command, and any errors that were added to the $error log by the command. When you invoke Get-History, the new default format for extended history information presents most of these details, or you can pipe the results to Format-List * to get all properties where you can see the core history properties as well as the extended information added by HistoryPx.
In addition to providing extended history information in PowerShell, the HistoryPx module includes one other feature that is quite useful. It defines a double-underscore ($__) variable in the global scope that will always contain the output of the last command that was executed. When the last command doesn’t have any output, $__ will be assigned a value of $null. This comes in handy when you invoke a command that takes time to complete but forget to capture the results in a variable.
If you want to give this module a try, head on over to the HistoryPx page on GitHub where you can learn how to install or update it in your environment and read additional details provided in the readme file on GitHub. If you are concerned about memory usage with this module, your questions are addressed in the readme as well. This is only the first release of this module, and I am already starting to track features that I want to add to another release. If you do give it a try, please let me know what you think, either in the comments on this blog post or in GitHub, and please log any issues you find on GitHub as well.