![]() |
Platforms, Frameworks & Libraries »
Windows Powershell »
General
Intermediate
License: The Code Project Open License (CPOL)
Saving Powershell commands across sessionsBy Gideon EngelberthA set of functions to provide the ability to save commands to be used in future Powershell sessions. |
Windows (WinXP, Win2003, Vista), .NET (.NET 2.0), DBA, Dev, SysAdmin
|
||||||||
|
Advanced Search Add to IE Search |
|
|
|
||||||||||||||||
Powershell is a useful tool
for developers and system administrators alike. Much of its usefulness
comes from being able to craft a complicated, multi-part command to get
some useful piece of information. The problem is that once I close the
window, the command is gone. If I really want to save that command, I
could make a script, but that involves taking several steps to open a
text editor, type in the command, and save the script file.
Furthermore, I then have to either type in the full path of the script
when I want to run it later. Also, when I make a script, I feel the
need to include descriptive comments such as the purpose of and
arguments to the script. All I really want is a quick and easy way to
save commands and execute them later.
Doing a little searching on the web revealed the Get-History cmdlet, which allows you to see the entire command history that has been saved so far. There is also the Add-History cmdlet, but my attempts to use it to load in saved commands proved unsuccessful. The commands would be shown by Get-History but did not appear to be accessible via the up or down keys, which are the normal way to cycle through the history.
Even if it had worked, I wanted a way to be able to save an arbitrary number of commands and be able to execute them easily without having to arrow through the history. Another shortcoming of that approach is that the loaded commands would eventually be pushed out of the history, requiring some method to reload the commands into the history. With those limitations in mind, I set about writing my own functions.
Why functions and not a set of script files? The main reason for using functions instead of script files is that I can call them from any location without having to type the path to the directory where I keep my scripts. Once the functions have been added to the $profile file, the functions will be loaded every time Powershell starts and be available for use without any further intervention from me. Since I am too lazy to type out the entire function names every time, I also set a short alias in the $profile file for each of the functions. For those not as familiar with Powershell, it is as simple as this:
Set-Alias nsc NewSaveCommand
The key to making this all work is that Powershell has a eval type function. The Invoke-Expression cmdlet will take a string either through the pipeline or as an argument and execute it as a Powershell command. This allows you to save a command into a small text file and later load and execute the command.
There are four functions needed for the full set of features. They are:
The function of each should is indicated by the name, but the way they work is worth explaining.
NewSavedCommand will save the last command entered (before the command to save the last command, of course) to a text file in the same directory as your Powershell profile file. The name of the file is in the form <number>.psc, where the number chosen is the smallest number that is not already taken. This means that if you have several commands and start deleting them, the next commands you add will fill in the blank numbers instead of being added to the end while leaving gaps.
RemoveSavedCommand will remove a saved command that you no longer want to keep around. This will free up the command number to be used again by the next command you save. If you pass a negative number to the function, ALL of your saved commands will be deleted. You have been fairly warned.
GetSavedCommand can either print a list of all saved commands or can print out the entire text of a particular saved command. In the screenshot, you can see the results of passing no argument (or a negative one) to the function. One of my commands is quite long and goes off the screen. To see the entire command, I simply call the function again with the number of the command I want to see. That command is one that I will probably want to call throughout the next few weeks, and you can see how useful it is to not have to remember and retype the entire thing.
ExecuteSavedCommand takes the number of the command to be executed as a parameter and will read in the contents of <number>.psc and pass that to Invoke-Expression. The result will be that your complicated, specially crafted command will be executed, without having to type in the entire text again.
One interesting thing I came across while making these functions is the ability to format your output as a table without having predefined classes and properties. The first call to GetSavedCommand in the screen shot shows the results. Here's the corresponding code:
Get-ChildItem (Split-Path $profile -parent) *.psc |
Format-Table @{Label='Number';
Expression={[int]([System.IO.Path]::GetFileNameWithoutExtension($_.FullName))}},
@{Label='Command'; Expression={Get-Content $_.FullName}} -auto
If you are not familiar with Powershell, a few notes about the syntax are in order. The @{} creates a hashtable that can be filled with key-value pairs. The semicolon is used as a separator because the comma is already used to make arrays (no braces or parentheses are needed to make an array, just a list of comma separated values). For those used to coding in C style languages, you may guess that the Expression value is a block of code, and you would be correct.
Format-Table is a built-in cmdlet that allows you to pass the object to be formatted through the pipeline and specify the properties as arguments. If you want to show something that is not a property, however, you will need to use the hashtable syntax shown above. The Label is the name that will be shown at the top of the column and the Expression is a code block that calculates the value for that column. The -auto argument simply tells the cmdlet to auto-size the columns to prevent a lot of whitespace.
After creating the functions, I thought of a few potential improvements that I decided not to implement for my own use. They should not be too difficult to add, and I would be willing to add them if several people would find them useful.
21 May 2008
| You must Sign In to use this message board. | ||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||
General
News
Question
Answer
Joke
Rant
Admin
|
PermaLink |
Privacy |
Terms of Use
Last Updated: 21 May 2008 Editor: |
Copyright 2008 by Gideon Engelberth Everything else Copyright © CodeProject, 1999-2009 Web21 | Advertise on the Code Project |