Create a Custom Tool to Find History with PowerShell

Not too long ago we published an article and PowerShell function you could use to copy a PowerShell command. You could use this technique to quickly build your own tools based on existing commands. Let me give you another example that’s a bit more detailed. First, there must be a need. For me, I want a quick way to get command history, but I want to limit my history to unique entries.

For example, here are the last 10 commands I have run using Get-History.

Using the Get-History cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)
Using the Get-History cmdlet in Windows PowerShell. (Image Credit: Jeff Hicks)

In case you were wondering, the gmb command is an alias for one of my functions to display battery life. You’ll see that I have some duplicate commands. I’d prefer to have a unique list, which I can do like this:

It works.

Creating a unique list with PowerShell's Get-History cmdlet. (Image Credit: Jeff Hicks)
Creating a unique list with PowerShell’s Get-History cmdlet. (Image Credit: Jeff Hicks)

But I don’t want to have to always type all of this. I’m happy with Get-History. I just need to add some functionality to it. So I’ll use my Copy-Command tool to create a new version of Get-History, where I’ll call Get-MyHistory. If you are following along, run this in the PowerShell ISE.

Without making any changes, the Get-MyHistory function is identical to Get-History because at its core, all I am doing is passing parameters to the underlying command.

I am splatting the automatic variable $PSBoundParameters to Get-History. My copy includes all the same parameters as well as complete comment-based help. Eventually, I will go back and modify the help to reference anything new that I add and to remove some things, such as the online help link to Get-History.

Remember, the purpose of creating my own tool is to simplify what I have to type at the prompt. I will also stress that this is a tool for me to use interactively, not something I would include in a script. If I did, I would have to make sure to include the Get-MyHistory function script.

Defining Parameters

Although my initial need was to find unique results, I don’t want to hard-code myself into a corner. There might be situations where I want to use my new tools to grab everything. We can do this by adding a switch parameter.

I also want an easy way to find previous commands using a regular expression pattern. Depending on my needs, I can remove existing parameters, add validation tests or set default values.

Begin Scriptblock

Code in the Begin block runs once, before any pipelined objects are processed, although that’s not really an issue with this command. What I prefer to do is insert some Write-Verbose commands that will provide some debug and trace information. Some of these commands are auto-generated when you run Copy-Command.

Assuming you intend to splat $PSBoundParameters to the original command, you have to pay attention to this variable. In this instance, Get-History isn’t designed to use –Unique or –Pattern. If I try to run Get-History with them, PowerShell will complain and throw an exception. That’s why you see me removing them from $PSBoundParameters. The variables still exist, so if I use –Pattern, I can still reference $Pattern in my function. They just aren’t part of $PSBoundParameters.

Process Scriptblock

In the Process scriptblock, I can grab history commands using the same parameters, ID and Count.

If I’m searching for a command based on a pattern, I filter the results.

Finally, I filter for unique history items if requested.

All that remains is to write the results to the pipeline.

I also decided I might want to know how long a command took to run so I added an additional property that is calculated at run time.

End Scriptblock

Code in the End scriptblock runs once after everything has been processed. In my case, I don’t have any cleanup to do, so I display a verbose message.

The Final Tool

When I load the function into my PowerShell session, I have a new tool at my disposal.

Get-MyHistory Help. (Image Credit: Jeff Hicks)
Get-MyHistory Help. (Image Credit: Jeff Hicks)

I can run it like Get-History.

Executing Get-MyHistory. (Image Credit: Jeff Hicks)
Executing Get-MyHistory. (Image Credit: Jeff Hicks)

Or I can use my new parameters.

Using parameters with Get-MyHistory. (Image Credit: Jeff Hicks)
Using parameters with Get-MyHistory. (Image Credit: Jeff Hicks)

The additional property is present but not part of the default display.

Here’s my result.

Out-GridView for Get-MyHistory results. (Image Credit: Jeff Hicks)
Out-GridView for Get-MyHistory results. (Image Credit: Jeff Hicks)

Without too much difficulty I created a new tool to get command history the way I want it. For the record, here’s the complete command.

I’m really liking the ability to copy commands and create my own tools. I have a few more that will be sharing with you. And if you’ve built something cool, I hope you’ll let everyone know in the article comments.

Related Topics:

  • PowerShell

    Don't have a login but want to join the conversation? Sign up for a Petri Account