Summary: Microsoft Scripting Guy, Ed Wilson, talks about avoiding Windows PowerShell scripting by using command history.
Hey, Scripting Guy! I used to have a program that I could use to keep track of commands I typed at the command prompt. It permitted me to use macros to replay those commands or to select which commands I wanted to run. It was simple, elegant, and not complicated. It is a shame that “modern” programs are not that easy to use. I really don’t relish the thought of having to learning scripting to be able to run a few commands. I wish I could go back to my old command prompt. But I guess I cannot. No action required. I am just letting off steam today. Thanks for listening.
—LM
Hello LM,
Microsoft Scripting Guy, Ed Wilson, is here. The Scripting Wife and I were out and about the other day, before the snow storm hit, and we ran across a little tea shop that had a very nice Lapsang Souchong tea. It is one of the few teas that I drink with milk. I find I need the milk to help cut the rather strong, unique flavor. If you haven’t had this tea, you may want to try it sometime—but don’t rush out and buy a pound of it just yet. It is a bit of an acquired taste, and you might not like it.
It is a good tea to try off a nice tea menu to see if you like it. I find it goes really well with Scottish butter cookies—but again, that may be me. I find the combination to be a bit “old school”; but then, it may be that I fell in love with the combination a long time ago when we were in Australia for the first time.
Speaking of old school...
Yeah, I think I may remember using an old-fashioned command prompt a long time ago. It was simple—but I also remember some of the commands were pretty convoluted, and they all seemed to act differently. The good thing, LM, is that you can use the Windows PowerShell console in a similar fashion to how you used the command line. You do not have to learn scripting if you do not want to. All you need to do is to use the command history.
Windows PowerShell command history
There are a number of Windows PowerShell cmdlets that permit working with the command history. I can find them by using the Get-Command cmdlet, and then looking for a name that matches History and a command type that equals Cmdlet. Here is the command and the results:
PS C:\> Get-Command -Name *history* -CommandType cmdlet
CommandType Name ModuleName
----------- ---- ----------
Cmdlet Add-History Microsoft.Powe...
Cmdlet Clear-History Microsoft.Powe...
Cmdlet Get-History Microsoft.Powe...
Cmdlet Invoke-History Microsoft.Powe...
To see the commands in my history, I use the Get-History cmdlet:
PS C:\> Get-History
Id CommandLine
-- -----------
7 clhy
8 cls
9 h
10 cls
11 Get-Command -Noun history
12 cls
13 Get-Command -Noun history -CommandType cmdlet
14 Get-Command -Noun history -CommandType Cmdlet
15 Get-Command -Noun history
16 Get-Command Get-Command -Syntax
17 cls
18 Get-Command -Name *history* -CommandType cmdlet
If I find myself using the Get-History cmdlet often, I can use an alias. Here is the Get-Alias command:
PS C:\> Get-Alias -Definition Get-History
CommandType Name ModuleName
----------- ---- ----------
Alias ghy -> Get-History
Alias h -> Get-History
Alias history -> Get-History
If I want to run a command from the history, I use the Invoke-History cmdlet. I generally use Get-History and Invoke-History together. I need to see what is in my history before I can execute a prior command. The easiest way to run something from the history is to specify the command ID. This technique is shown here:
PS C:\> Get-History
Id CommandLine
-- -----------
21 clhy
22 cls
23 Get-History
24 cls
25 Get-Service bits
26 Get-Process explorer
27 cls
PS C:\> Invoke-History -Id 25
Get-Service bits
Status Name DisplayName
------ ---- -----------
Running bits Background Intelligent Transfer Ser...
As shown here, I can specify an array of ID numbers for the Get-History cmdlet:
PS C:\> Get-History -Id 25, 26
Id CommandLine
-- -----------
25 Get-Service bits
26 Get-Process explorer
But when I attempt to use an array of IDs with the Invoke-History cmdlet, I get the following error message:
Hmmm…
Well, I can pipe the results from Get-History to Invoke-History:
PS C:\> Get-History 25 | Invoke-History
Get-Service bits
Status Name DisplayName
------ ---- -----------
Running bits Background Intelligent Transfer Ser...
Because I can get multiple items from the history, can I also pipeline them? As shown in the following image, I still get an error message:
Bummer.
When I see an error message that says a cmdlet will not accept multiple items through the pipeline, I can usually substitute the command for one that includes Foreach-Object. This is because Foreach-Object interrupts the pipeline and deals with each item, one at a time. It ruins “streaming” the output, but it permits me to pipe the results from one command to another. I can also automate the output without having to resort to scripting. Here is the revised command:
Get-History -Id 25, 26 | foreach { Invoke-History -id $_.ID}
As shown in the following image, the command works:
LM, that is all there is to using the Windows PowerShell command history. Script Without Scripting Week will continue tomorrow when I will talk about more cool stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy