|
|||||||||||||||||||||||||||||||||||||||||||||
|
|||||||||||||||||||||||||||||||||||||||||||||
|
Announcements
Want a new Job?
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionPowershell 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. BackgroundDoing 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:
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. Using the codeThere 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. Points of InterestOne 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 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 Room For ImprovementAfter 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.
History21 May 2008
|
||||||||||||||||||||||||||||||||||||||||||||