Summary: Learn best practices for using the Windows PowerShell aliases at the command line and in scripts. Microsoft Scripting Guy, Ed Wilson, is here. The 2012 Scripting Games are nearly over. The judges are all working, nearly around the clock, to get the final scripts graded so the final leaderboard will reveal this year’s top scripters. In a very real sense, everyone who participated is a winner because you have taken a positive step towards increasing your knowledge and understanding of a most exciting technology. One of my favorite tweets from this year’s games was one that said, “The Scripting Games is not a sprint, it is a marathon.” Just like marathon runners try to increase each year’s performance to achieve their personal best—so too is that the case with the Scripting Games.
Understanding aliases
Aliases are shortcuts to commands. One of the strengths of Windows PowerShell is that it is very readable code. For example, to get information about processes, the command is Get-Process. But this strength in readability is also a weakness, because it requires typing 11 characters just to get a list of processes. Of course, when compared to typing in dozens of lines of obscure VBScript code to perform the same task, 11 characters seems like a real bargain. But, people are always looking to do more with fewer resources, and scripting is no different. “Why do I have to type 11 characters to get a listing of processes when in (x, y, or z) shell I only need to type two letters to get the same information?” they may ask. One way to address this is to use tab completion. By using tab completion, you only need to type Get-P and hit the Tab key once or twice until the command Get-Process appears, and then you hit ENTER to execute the command. By doing this, you are typing only five characters, and therefore, saving over 50% of the number of key strokes required to type Get-Process. The advantage of using tab completion is that you maintain readability and you reduce the number of key strokes required to type complete commands. To find aliases for the Get-Process cmdlet, use the Get-Alias cmdlet. This technique is shown here (remember that you can use tab expansion to type this command).
PS C:> Get-Alias -Definition Get-Process
CommandType Name Definition
———– —- ———-
Alias gps Get-Process
Alias ps Get-Process In fact, there is an alias for the Get-Alias cmdlet. To retrieve the alias use Get-Alias as shown here.
PS C:> Get-Alias -Definition Get-Alias
CommandType Name Definition
———– —- ———-
Alias gal Get-Alias When you use Get-Alias, you need to remember that it is used in different modes. With the first mode, the default is to resolve an alias to a Windows PowerShell command. Because the Name of the alias is the default parameter, you can use it as a positional parameter. I will talk about positional parameters later. For now, this means that you can use the gal alias for the Get-Alias cmdlet, and attempt to resolve the meaning of an alias named ps by typing the cryptic command that is shown here.
PS C:> gal ps
CommandType Name Definition
———– —- ———-
Alias ps Get-Process
Three main problems with aliases
There are essentially three problems when using aliases. The three problems are readability, understandability, and guarantee ability.
The problem of readability
Clearly, it is easier to read and to understand a command that looks like Get-Content than it is to understand a command that looks like gc. At times, it might be possible to figure out what an alias might mean by looking at it, but many times the alias might be a bit obscure. This is especially true when positional and partial parameters enter the picture. Is the following command good, bad, or indifferent?
gsv bits | spsv -wh
The problem of understandability
Because they are harder to understand, the use of aliases makes code more difficult to troubleshoot. It might take less time to type, but if the command does not work properly, it will take more time to troubleshoot simply because the code is more obscure. Typing a command, such as the one that is shown here, from the Windows PowerShell console is fairly easy to do, and it is great when it works. However, the code that appears is a bit difficult to understand for many people who use Windows PowerShell.
PS C:> ls | ? {$_.psiscontainer} | % {“{0}`t{1}” -f $_.name,$_.lastaccesstime}
1 2/10/2012 10:43:41 PM
2012SG 2/9/2012 10:08:32 AM
data 12/6/2011 11:54:42 PM
driver 12/5/2011 9:21:14 PM
DRIVERS 12/12/2011 4:01:25 PM
fso 3/8/2012 6:38:12 PM
Intel 12/12/2011 4:07:56 PM
LogonLog 2/9/2012 4:30:18 PM
PerfLogs 7/13/2009 11:20:08 PM
Program Files 12/11/2011 1:35:38 PM
Program Files (x86) 2/20/2012 4:56:42 PM
SWTOOLS 12/11/2011 1:26:46 PM
Users 12/12/2011 4:09:22 PM
Windows 3/29/2012 11:26:51 AM Now, what happens to the code when introducing an error into the mixture? Especially when the error does not display an error!
PS C:> ls | ? {$_.pscontainer} | % {“{0}`t{1}” -f $_.name,$_.lastaccesstime}
PS C:> The longer version of the command is a bit easier to read. The code is still a bit convoluted, but at least you can start to get an idea about what the command is supposed to do.
Get-ChildItem | Where-Object {$_.psiscontainer} | ForEach-Object {“{0}`t{1}” -f $_.name,$_.lastaccesstime}
The problem of guarantee ability
Simply put, you can never be sure if an alias exists for a particular environment. There are three different types of aliases: compatibility, native, and custom. Compatibility aliases are aliases that make the transition from DOS to Windows PowerShell or from UNIX to Windows PowerShell easier. Aliases in this category include dir, ls, cat, type, and so forth. The compatibility aliases are not protected, and they are easily deleted at any time. To see all of the compatibility aliases, look for aliases that do not have the ReadOnly option set. The following command does just that.
Get-Alias | Where-Object { $_.options -notmatch ‘readonly’} The native aliases are aliases that are only meaningful within Windows PowerShell. You will not necessarily find a command in a UNIX or DOS environment that has the same command. These aliases have the ReadOnly option set. The following command displays all of the native aliases.
gal | ? { $_.options -match ‘readonly’} The thing is, read-only aliases are removable. To delete an alias, you use the Remove-Item cmdlet and choose the alias from the alias drive. A read-only alias generates an error unless you use the Force parameter. This technique is shown here.
PS C:> Remove-Item alias:gc
Remove-Item : Alias was not removed because alias gc is constant or read-only.
At line:1 char:12
+ Remove-Item <<<< alias:gc
+ CategoryInfo : WriteError: (gc:String) [Remove-Item], SessionStateUn
authorizedAccessException
+ FullyQualifiedErrorId : AliasNotRemovable,Microsoft.PowerShell.Commands.Remov
eItemCommand
PS C:> Remove-Item alias:gc -Force
PS C:> But deleting an alias from the alias drive does not remove it forever. It merely removes it from the current session. However, if you add the remove alias command to your Windows PowerShell profile, you effectively remove the alias forever. In fact, it is not uncommon to remove a canonical alias and to redefine the alias to something more useful. To do this, merely add the commands to your Windows PowerShell profile. Each time Windows PowerShell starts, it removes the offending alias and replaces it with your custom alias. Here is an example of changing GC from being an alias for Get-Content to being an alias for Get-Command.
Remove-Item alias:gc -force
Set-Alias -Name gc -Value Get-Command Note I am not advocating that you replace canonical aliases with your own custom aliases. I think that it could lead to unpredictable results—especially when you run code from other people who do, in fact, use aliases in their scripts. I am pointing out that such a situation is not unusual and that one must be careful when using aliases.
Best practices when working with aliases
First, if you completely control the environment and you never run code from outside your organization, then there is no problem using aliases. In fact, I know of some organizations that have a profile that defines organizational wide aliases. In addition, it is relatively easy to create a central Windows PowerShell profile so that no matter what machine you log on to, you will always have your aliases available. If this is the situation, and if the aliases utilized are clearly understood by everyone involved, go ahead and use aliases wherever you wish because you have mitigated all three of the problems mentioned earlier. However, if you are sharing code outside your organization, or you are running code from outside your organization, it makes sense to mitigate the potential problem of aliases by not using them in scripts. Because Windows PowerShell is a scripting language and an interactive command shell, there are two best practices:
- Use aliases when working interactively at the console
- Don’t use aliases in scripts
Use aliases when working interactively at the console
When you are working interactively at the console, and as you learn new aliases, you can save yourself a considerable amount of time by using certain aliases. There are four one-letter aliases, and these are the least amount of typing possible. You should certainly add them to your repertoire. The following command displays these aliases.
PS C:> Get-Alias ?
CommandType Name Definition
———– —- ———-
Alias % ForEach-Object
Alias ? Where-Object
Alias h Get-History
Alias r Invoke-History
Don’t use aliases in scripts
If you are writing a script, you are creating an artifact that you will supposedly use again. Because it is more permanent, you should take a bit of extra time and resolve all aliases. In a script, you should not assume anything about the environment that will run the script. Of course, in real life, it is common to make all kinds of assumptions. Some of the more common assumptions are the version of the operating system and the requirement for administrative rights. Another big assumption, when a script accepts command-line parameters, is that the user will enter the correct type of information that the parameter requires. Another common assumption is that an alias will be present when required. How does this happen? When developing and when testing the script, it is common to run the script on your own computer. But because the script works on your computer, does not mean that it will work on my computer. This is especially true when using aliases. When you find an alias that you like, it is common to add that alias to your profile if it does not previously exist. Over time, you get used to using the alias until it becomes second nature. At that point, you may forget that it is a custom alias and expect it to exist everywhere. To avoid inadvertently introducing a user-defined alias into a production script, do not use any alias in the script. It is absolutely the safest approach. The added bonus is that your scripts will be easier to read and to understand. Consequently, the script will also be easier to troubleshoot, maintain, and modify in the future. 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
0 comments