Bookmark and Share

 

Hey, Scripting Guy! Question

Hey, Scripting Guy! I have been playing around with Windows PowerShell 2.0 in Windows 7 and I think that I like it. However, it seems to require an awful lot of typing. The double command names, such as Get-Process, are somewhat helpful for remembering things, but it is quite a bit of typing. Yes, it is shorter than writing a VBScript to return the same information, but did you have to make everything so long? And by the way, while I am whining, I hate typing the hyphen. It is too hard to find on my keyboard. I do not expect you to change Windows PowerShell just for me, but surely there are others out there who feel the same way I do. If Windows PowerShell is supposed to be the all-new management tool for administrators, you could have made it easier to use.

-- RR

Hey, Scripting Guy! AnswerHello, RR.

Microsoft Scripting Guy Ed Wilson here. Well I just got off a two-hour Live Meeting with a customer. I was talking about some of the new remoting features in Windows PowerShell 2.0. It was an awesome talk, if I do say so myself. I love talking to customers, and I love working with Windows PowerShell 2.0. On those occasions when I combine those two passions, it is a great day.

RR, it seems that I need to introduce you to the concept of aliases. Consider a command such as Measure-Object that is used to count information and provide statistical information such as the minimum and maximum values of an object. Measure-Object can be a bit cumbersome to type from a command line, and given the relative frequency of its use, it becomes a good candidate for aliasing.

Note: Portions of today's Hey, Scripting Guy! post are excerpted from the Microsoft Press book, Windows PowerShell 2.0 Best Practices by Ed Wilson. The book is available for pre-order.

Verifying the existence of an alias

Before creating a new alias, it is a best practice to see if there is a suitable alias already created for the cmdlet in question. By default, Windows PowerShell ships with more than 130 predefined aliases for its 271 cmdlets. When you consider that several of the cmdlets have more than one alias defined, you can see there is great opportunity for the creation of additional aliases. The ListCmdletsWithMoreThanOneAlias.ps1 script lists all cmdlets that have more than one alias defined. This script is seen here.

ListCmdletsWithMoreThanOneAlias.ps1

Get-Alias |
Group-Object -Property definition |
Sort-Object -Property count -Descending |
Where-Object { $_.count -gt 2 }

 

When the ListCmdletsWithMoreThanOneAlias.ps1 script runs, the following appears:

Count Name                      Group
----- ----                      -----
    6 Remove-Item               {del, erase, rd, ri...}
    3 Set-Location              {cd, chdir, sl}
    3 Get-History               {ghy, h, history}
    3 Get-ChildItem             {dir, gci, ls}
    3 Get-Content               {cat, gc, type}
    3 Move-Item                 {mi, move, mv}
    3 Copy-Item                 {copy, cp, cpi}

To see if an alias for the Measure-Object cmdlet exists already, you can use the Get-Alias cmdlet and the -definition parameter as shown here:

PS C:\> Get-Alias -Definition Measure-Object

CommandType     Name                                      Definition
-----------     ----                                      ----------
Alias           measure                                   Measure-Object

If you like the alias measure, you can use that alias. However, you may decide that the readability of the alias measure is hampered by the fact, that it only saves two key strokes. Because of the implementation of the tab expansion feature, all you need to do is type measure-o and press TAB. In general, when creating personal aliases, I prefer to sacrifice readability for ease of use. My very favorite aliases are one-letter and two-letter aliases. I use the one-letter aliases for commands I frequently use, because they are the most useful and most obscure. I use the two-letter aliases for most of my other alias needs. The two-letter combination can easily correspond to the verb noun naming convention. Therefore, mo would be a logical alias for the Measure-Object cmdlet. To ensure its availability, use the Get-Alias cmdlet as shown here:

PS C:\> Get-Alias -Name mo

How many two-letter aliases are there?

The two-letter alias namespace is rather large. How large? You have to take every letter in the range A-Z, and pair it with every other letter in the range of A-Z. If you are good with algebra then you immediately know there are 676 possible letter combinations (26 x 26). However, if your algebra is a bit rusty, you may wish to write a Windows PowerShell script to figure it out for you. The problem with such an approach is that we cannot use the range operator to produce a range of letters. It works with numbers, so 1..10 automatically creates a range of numbers with the values 1 through 10, and can save you a lot of typing. However, because we have ASCII numeric representations of the letters A-Z, you can use this technique to create a range of letters. The ASCII value 97 is the “A” character, and the ASCII value 122 is “Z”. After we have the numeric range, we use the ForEach-Object cmdlet and convert each letter to a character by using the [char] type. We store the resulting array of letters in the $letters variable. We then do two loops through the array and store the resulting letter combinations in the $lettercombination variable, which is constrained as an array by using the [array] type. The Measure-Object cmdlet is used to count the number of possible letter combinations. The ListTwoLetterCombinations.ps1 script is shown here.

ListTwoLetterCombinations.ps1


$letterCombinations = $null
$asciiNum = 97..122
$letters = $asciiNum | ForEach-Object { [char]$_ }
Foreach ($1letter in $letters)
{
 Foreach ($2letter in $letters)
 {
  [array]$letterCombinations += "$1letter$2letter"
 }
}
"There are " + ($letterCombinations | Measure-Object).count + " possible combinations"
"They are listed here: "
$letterCombinations

To create a new alias, you can use either the New-Alias cmdlet or the Set-Alias cmdlet. You could also use the New-Item cmdlet and target the Alias drive. The problem with that technique is it does not support the Description parameter, which allows you to specify additional information about the alias. The other problem with using the New-Item cmdlet to create an alias is that it is more typing. So as a best practice, I always use either the New-Alias or the Set-Alias cmdlet.

In choosing between the two cmdlets, which should you use when creating a new alias? Before we answer that, we should actually talk about what the cmdlets are intended to be used for. The New-Alias cmdlet, obviously creates a new alias. The Set-Alias cmdlet is used to modify an existing alias. If an alias does not exist, it will create the alias for you. Therefore, many people use the Set-Alias cmdlet to both create and modify an alias. There is a danger in this approach, however, in that you can inadvertently modify a previously existing alias with no notification. If this is your desired behavior, that approach is fine. A better approach is to use the New-Alias cmdlet when creating an alias. This allows you to specify the Description parameter, and to receive notification if an alias that you are trying to create already exists. To assign a description to an alias when creating it, you use the Description parameter as seen here:

New-Alias -Name mo -Value Measure-Object -Description "MrEd Alias"

In an enterprise-scripting environment, many companies like defining a corporate set of aliases—this provides for a consistent environment. A network administrator working on one machine can be assured that a particular alias is available. This also helps to ensure a predictable and consistent environment. By using the same value for the Description parameter of the alias, it is easy to list all the corporate aliases. To do this, you would filter the list of aliases by the description. An example of this is seen here:

PS C:\> Get-Alias | Where-Object { $_.description -eq 'mred alias' }

CommandType     Name                                      Definition
-----------     ----                                      ----------
Alias           mo                                        Measure-Object

When using the -eq operator in the code block of the Where-Object cmdlet, the filter is case insensitive. If you need a case sensitive operator, you would use -ceq. The “c” is added to all the operators to form a case sensitive form of the operator—by default the operators are case insensitive. As shown here, when using the case sensitive operator, the filter does not return any aliases:

PS C:\> Get-Alias | Where-Object { $_.description -ceq 'mred alias' }
PS C:\>

In addition to specifying the Description parameter, many companies also like to use the Option parameter to make the alias either read-only or constant. To make the alias read-only, you supply the readonly keyword to the Option parameter. This is shown here:

New-Alias -Name mo -Value Measure-Object -Description "MrEd Alias" -Option readonly

The advantage of making the alias read-only is that it offers protection against accidental modification or deletion. This is seen here:

Image of read-only alias protecting against modification or deletion


There is an additional advantage to making the alias read-only: It can be modified or deleted if needed. If you wish to modify the description, you use the Set-Alias cmdlet to specify the name, value the new description, and use the Force parameter. This is seen here:

Set-Alias -Name mo -value measure-object -Description "my alias" –Force

If you need to delete a read-only cmdlet, you use the Remove-Item cmdlet and specify the Force parameter. This is seen here:

Remove-Item Alias:\mo -Force

To create a constant alias, you use the constant keyword with the option parameter. This technique is shown here:

New-Alias -Name mo -Value Measure-Object -Description "MrEd Alias" -Option constant

As a best practice, you should not create constant aliases unless you are certain you do not need to either modify them or delete them. This is because a constant alias can be neither modified nor deleted—in effect, they really are constant. The error message is a bit misleading in that it says the alias is either read-only or constant, and it suggests attempting to use the Force parameter. The reason this is misleading is the message is displayed even when the command was run with the Force parameter. This error message is seen here:

Image of error message

 

Well, RR, this should get you started on using aliases in Windows PowerShell. Join us tomorrow as we continue examining ways to customize our Windows PowerShell environment.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post them on the Official Scripting Guys Forum. See you tomorrow. Until then, keep on scripting!

 

Ed Wilson and Craig Liebendorfer, Scripting Guys