Top Ten Favorite PowerShell Tricks: Part 2

Top Ten Favorite PowerShell Tricks: Part 2

  • Comments 1
  • Likes

Learn Top Tricks for Quickly Learning Windows PowerShell

Summary: The Microsoft Scripting Guy shares more of his top 10 tricks for working effectively with Windows PowerShell.

Microsoft Scripting Guy, Ed Wilson, is here. The weather in Charlotte, North Carolina quickly changed from nice, pleasant spring to hot and sticky summer. It seems that spring lasted for about a week—now it is summer. I am not a “get outside and swelter in the hot humidity” kind of a Scripting Guy. I am more of a find a nice cool spot for my laptop kind of Scripting Guy. Anyway, yesterday I began my top ten list of favorite Windows PowerShell tricks. Today I will continue the top ten list with Scripting Guy favorite PowerShell Tricks 5, 6, and 7. See tommorow's post for tricks 8-10.

Weekend Scripter

Trick #5: Use square brackets to index into an array

Many times Windows PowerShell cmdlets return a collection, or an array of objects. To work with collections or arrays it is often common to send the collection over the pipeline, or to store the information in a variable and use the ForEach statement to iterate through the collection. Inside the pipeline (or loop), when one has an individual object, one can then examine its members. Often when I am experimenting or exploring from the Windows PowerShell console, I do not want to take the time to set up a loop to work with the object. Instead I will index directly into the array by using square brackets. An array begins numbering at 0 in Windows PowerShell, and therefore I can always use [0] to retrieve the first record in the array (or collection). I can even combine this technique with my grouping trick from yesterday…use a pair of parentheses to force evaluation of the command. This technique is illustrated here.

PS C:\> (Get-Service)[0]

 

Status   Name               DisplayName

------   ----               -----------

Stopped  AdtAgent           Operations Manager Audit Forwarding...

 

 

PS C:\> (Get-EventLog -LogName application)[0]

 

   Index Time          EntryType   Source                 InstanceID Message

   ----- ----          ---------   ------                 ---------- -------

  118582 May 14 13:17  Information Office Software P...   1073742827 The Software Protection ser...

You will notice that the event log command takes a long time to return the first record. This is because the command syntax says to get all of the records from the application log and then index them into the first record. This is a very inefficient way to accomplish this task. It is better to use the Newest parameter as shown in the following command.

PS C:\> Get-EventLog -LogName application -Newest 1

 

   Index Time          EntryType   Source                 InstanceID Message

   ----- ----          ---------   ------                 ---------- -------

  118582 May 14 13:17  Information Office Software P...   1073742827 The Software Protection ser...

Trick #6: Use tab expansion

One of the great benefits of working interactively in the Windows PowerShell console is tab expansion. During the 2011 Scripting Games, we discouraged the use of aliases because of the emphasis on scripts. But when working interactively in the Windows PowerShell console, the use of aliases is a great benefit because it makes things go so much quicker. But one of the reasons I am experimenting in the first place is because I will one day incorporate what I learn into a script.

I wrote a Windows PowerShell ISE add-in that will replace Windows PowerShell aliases with the actual Windows PowerShell cmdlet name in a script, but that is still an extra step. Besides, when I use the History command, at times all the aliases get a bit confusing. To mitigate this, I use tab expansion extensively. In this way, I get the benefit of quick typing, and I have the added benefit that if I copy the command to the Windows PowerShell ISE, I do not need to translate it—the command is complete and ready to go.

Therefore, if I want to use the Get-Process cmdlet, there is an alias, gps. But I can also type Get-p and press the <tab> key, and it will complete the command. If there are several matches (as is the case with Get-p), I simply press the <tab> key again and again until the command I wish to use appears. If I accidently go too far (i.e., I pressed <tab> too fast and skipped past the command I wanted), I can hold down the <shift> key and press <tab>, and it returns to the previous command.

The really cool thing about tab expansion is that it works for parameter names as well. For clarity, I advocate always using full parameter names in scripts, and quite often, I will include them when working interactively in the Windows PowerShell console (they are often required depending on the parameter set).

Adding parameter names is really easy. After the Windows PowerShell cmdlet name (or alias) is in place, I type a dash (-) and press the <tab> key to bring up the first parameter name. I continue pressing <tab> until I find the parameter I want to use.

The big reason I might choose to leave out parameter names, or use aliases extensively, is when the Windows PowerShell command is growing to the point it consumes multiple lines in the Windows PowerShell console. At this point, the command becomes difficult to work with and I therefore use aliases to shorten the command.

You should learn a few aliases (especially the one letter ones) so you will become more productive in the Windows PowerShell console. To see all of the one-letter aliases, use the following command.

PS C:\> Get-Alias ?

Here is the command output: 

CommandType     Name                                      Definition

-----------     ----                                      ----------

Alias           %                                         ForEach-Object

Alias           ?                                         Where-Object

Alias           h                                         Get-History

Alias           i                                         Invoke-History

Alias           r                                         Invoke-History

(Note: The i alias is one that I created and placed in my Windows PowerShell profile. For more information about aliases, refer to this series of Hey! Scripting Guy blogs. For more information about Windows PowerShell profiles, see this series of Hey! Scripting Guy blogs)

If you are reading a blog somewhere, and you see an alias that you are not sure about, you can look that alias up by using the Get-Alias cmdlet. This is illustrated here.

PS C:\> Get-Alias %

 

CommandType     Name                                      Definition

-----------     ----                                      ----------

Alias           %                                         ForEach-Object

Because the question mark is a wildcard character (for a single character), the Get-Alias cmdlet interprets its use as a wildcard; and therefore, it returns the one letter aliases. If I want to look up the meaning of the ? alias, I need to escape the ? character with the back tick. This is shown here.

PS C:\> Get-Alias -Name '`?'

 

CommandType     Name                                      Definition

-----------     ----                                      ----------

Alias           ?                                         Where-Object

If you really like using tab expansion, you can enhance its ability by modifying the TabExpansion function. A better bet is to use PowerTab, the enhanced tab expansion function from CodePlex.

Trick #7: Use –list to easily find WMI classes

Most people know that they can easily produce a list of WMI classes. This is illustrated in the following image.

Image of command output

If I need to find WMI classes that are related to memory, I add *memory* just after the List parameter. This will filter out only WMI classes that contain the word Memory within the class name. This is illustrated in the following image.

Image of command output

Most of the time, I do not mind weeding through the list of WMI class names that are returned. However, at times, I am looking for something rather specific. For example, suppose I am looking for formatted performance counter classes that are related to memory. To find this, I add a little bit to my wildcard filter. The command I came up with is shown here.

Get-WmiObject -List win32*perfFormatted*memory*

The command and its associated output appear in the following image.

Image of command output

As you can see, the complete class names are truncated. I get around that by using the Select-Object cmdlet as shown here (Select is an alias for the Select-Object cmdlet).

PS C:\> Get-WmiObject -List win32*perfFormatted*memory* | select name

 

Name

----

Win32_PerfFormattedData_MSSQLSQLEXPRESS_MSSQLSQLEXPRESSMemoryManager

Win32_PerfFormattedData_NETFramework_NETCLRMemory

Win32_PerfFormattedData_NETMemoryCache40_NETMemoryCache40

Win32_PerfFormattedData_PerfOS_Memory

I will continue my top ten list of Windows PowerShell tricks tomorrow, when I reveal favorite tricks 8-10.

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

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Don't forget the format-table -AutoSize alternative to work around truncated outputs

    PS U:\>  Get-WmiObject -List win32*perfFormatted*memory* | ft -AutoSize

      NameSpace: root\cimv2

    Name                                                      Methods Properties

    ----                                                      ------- ----------

    Win32_PerfFormattedData_NETFramework_NETCLRMemory         {}      {AllocatedBytesPersec, Caption, Description, Final...

    Win32_PerfFormattedData_NETMemoryCache40_NETMemoryCache40 {}      {CacheEntries, CacheHitRatio, CacheHits, CacheMiss...

    Win32_PerfFormattedData_PerfOS_Memory                     {}      {AvailableBytes, AvailableKBytes, AvailableMBytes,...