Summary: Learn how to use the Windows PowerShell Add-History cmdlet to customize the console for more efficient automation.
Hey, Scripting Guy! I love using the Windows PowerShell history cmdlets to simplify my server and workstation automation needs. It is much easier to Invoke-History than it is to write a script, even a simple script. This is especially true because in many places where I work the script execution policy is not enabled. Ed, it would be great if I could save my command session. I know I can create a transcript, open the transcript, cut, and paste into the Windows PowerShell shell, but I am hoping for a better way.
Hello PD, Microsoft Scripting Guy Ed Wilson here. When the Scripting Wife and I arrived at the hotel in St. Augustine, Florida I had to head out to the beach. The smell of the salt in the air, the sound of the sea gulls squawking as they patrolled the coastline for food and the chill of the breeze running along the sand dunes make for an enthralling experience. This time of year, St. Augustine is not thronged with tourists, and so I was able to get a pretty decent picture of the beach, and the ocean.
PD, When I am working in Windows PowerShell and I have a collection of commands that are working exactly the way I want them to work, I usually copy them to a script file. Of course, those script files eventually get lost, and months later, I end up reinventing the wheel (so to speak). A better way is to export the history cmdlets so that they can be reintroduced to the Windows PowerShell command environment later.
I know what you are thinking… (Really I do, because I had the same thought myself when I was talking to one of the developers about the history cmdlets).
I said (and I quote), “You have missed a real need with the history cmdlets. You need an Export-History cmdlet.”
To this, he patiently explained that all I have to do is to pipeline the results of the Get-History cmdlet to Explort-Clixml. “Oh,” I said, “That makes sense.”
Suppose I have been working in the Windows PowerShell console for a while, and I have typed several commands that I want to use again. I decide to save the commands, not as cut and paste from the console, nor as a transcript text file that includes both commands and output, but instead as rich command history objects. I want to check my history queue before exporting the commands, because there might be things in it that I do not want to save and reintroduce to my Windows PowerShell environment later. The following figure shows the results of the Get-History command.
To perform the task of exporting my command history, all I have to do is to use the Get-History Windows PowerShell cmdlet to retrieve the history of my previously typed cmdlets and I pipeline it to the Export-CliXML cmdlet to store the commands in an XML format that will permit reconstituting the commands back into a command history object. The exact command that I typed into my Windows PowerShell console appears here.
Get-History | Export-Clixml -Path c:\fso\mycommands.xml
The path c:\fso points to the “scratch” directory on my local computer. That folder is my junk folder that holds various text files I use for input when I am speaking at user groups. I use those same “demo” files for testing when writing scripts as well. The path has the advantage of being short, and I have used it since the introduction of VBScript (incidentally that is why it is called fso –for FileSystemObject which was the name of one of the more important COM objects in VBScript). Now it is as anachronistic as talking about “dialing” a telephone number, or looking at the “face” of a clock.
I now close out my Windows PowerShell console, and after reopening it, I use the Add-History cmdlet to my saved Windows PowerShell commands into the console. The command that achieves this task appears here.
Add-History -InputObject (Import-Clixml -Path C:\fso\mycommands.xml)
I now use the Get-History cmdlet to confirm that the command completed successfully. The results obtained by the Get-History cmdlet appear in the following figure.
Well, that worked well enough. The Get-History command (command ID 1) is the one I typed to prove that the command worked properly. However, what is unexpected is the Get-History command that appears at command ID 6. I must have typed that earlier, and it is unwanted. If I want to confirm my suspicions, I can import the command history file into a variable by using the Import-Clixml cmdlet. I will then be able to directly check its contents. The commands that do this, together with the associated output appear here.
PS C:\> $xml = Import-Clixml C:\fso\mycommands.xml
PS C:\> $xml
3 Get-EventLog -LogName application -Newest 3
Just as I suspected, there is an additional command in my file. Yesterday, I talked about how to use Get-History and Invoke-History to retrieve and to run Windows PowerShell commands.
That would be the next step here if I were finished. However, I want to have a clean command history file and not one with extraneous commands in it. To accomplish that task, I have to use a selective Get-History command. First, I check to see what is in my command history by using the alias h (instead of typing the full command name Get-History), and then I select the specific tasks (ID’s 3 through 5) using the technique I discussed yesterday. The commands and their associated output appear her.
PS C:\> h
2 Add-History -InputObject (Import-Clixml -Path C:\fso\mycommands.xml)
5 Get-EventLog -LogName application -Newest 3
8 $xml = Import-Clixml C:\fso\mycommands.xml
PS C:\> Get-History (3..5) | Export-Clixml -Path C:\fso\mycommands1.xml
Now I close and reopen the Windows PowerShell console, and import the commands from mycommands1.xml. I use the following Add-History command.
Add-History -InputObject (Import-Clixml C:\fso\mycommands1.xml)
When I use Get-History to check the contents of my Windows PowerShell history buffer, the results shown in the following figure appear.
If the presence of the Add-History command in the command history queue is bothersome, you can clear the history by using the Clear-History cmdlet. The sequence to do this appears here.
PS C:\> Add-History -InputObject (Import-Clixml C:\fso\mycommands1.xml)
PS C:\> Clear-History 1
PS C:\> h
4 Get-EventLog -LogName application -Newest 3
5 Clear-History 1
Of course, then you have a Clear-History command in your buffer. After you have imported your command, you run them by piping the results of the Get-History cmdlet to the Invoke-History cmdlet using the technique I discussed yesterday.
If the commands are something that you always want to have available, add the Add-History command to your Windows PowerShell profile. PD, there is one last thing I have to tell you. The maximum number of history commands is stored as a preference variable that is set to 64 as seen here.
PS C:\> $MaximumHistoryCount
To change this number (either by increasing or decreasing the number) perform a direct value assignment as shown here.
PS C:\> $MaximumHistoryCount = 128
PS C:\> $MaximumHistoryCount
This will last until you restart Windows PowerShell. To make the change permanent, add it to your Windows PowerShell profile.
PD, that is all there is to using the Add-History cmdlet. Neglected cmdlet week will continue tomorrow.
I invite you to follow me on Twitter or Facebook. If you have any questions, send email to me at email@example.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy