Working with Ranges, Dates, and Other Cool PowerShell Tricks
Summary: Microsoft Scripting Guy, Ed Wilson, concludes his three-part series about his top ten favorite Windows PowerShell tricks.
Microsoft Scripting Guy, Ed Wilson, is here. I got a little carried away with my top ten list of Windows PowerShell tricks over the weekend. I had originally intended it to be only a Weekend Scripter series, but as I began writing about the tricks, I wanted to tell you WHY the tricks are my favorite tricks, and then I wanted to illustrate different things that show how to use the tricks. Before I knew it, I had run out of space. Rather than wait until next weekend to complete the series, I decided to run the blogs consecutively. So this is part three of my series about my top ten Windows PowerShell Tricks.
In the first blog, I talked about using the transcript feature, finding hidden objects, using Select to expand properties, and grouping items so they are dot accessible. In the second blog, I continued my discussion about the my top ten Windows PowerShell tricks by talking about using a square bracket to index into an array, using tab expansion, and using the List parameter with the Get-WmiObject cmdlet to find WMI classes.
Trick #8: Use the range operator
One of my favorite things to do is to create an array of 10 elements with the value of 1 through 10 in just five key strokes. Here is the code.
1..10
When I run this code, it creates an array of numbers, numbered consecutively 1 through 10. If I store these numbers into a variable, I can index into the array and retrieve the value of the elements. Remember that an array is zero based; and therefore, $a[5] returns the sixth item in the array. This is shown in the following image.
If I need to create an array of negative numbers, I use a minus in front of the numbers. This is shown here.
PS C:\> -1..-5
-1
-2
-3
-4
-5
I can reverse the order in which the numbers are created as shown here.
PS C:\> -5..-1
-5
-4
-3
-2
-1
PS C:\> 4..1
4
3
2
1
PS C:\>
There are times when I need to perform a command multiple times—for example, when refreshing Group Policy while waiting for replication to occur. In the following command, I call GPUpdate five times. I display a string to the Windows PowerShell console to let me know what pass has occurred and the time that pass ran. I also pause the script for ten seconds to wait between iterations of the command. The % character is an alias for the ForEach-Object cmdlet. The ; character is a command separator (it is an end-of-logical-line terminator). Therefore, the command inside the curly brackets is actually three separate commands.
1..5 | % { gpupdate ; “update $_ $(get-date)” ; sleep 10 }
When the command runs, the following output is produced on my system.
One day, I needed to create an array of letters. I thought I would try my range operator trick, and so I typed the command shown here.
A..Z
Unfortunately, the range operator does not work for letters, only for numbers. I then remembered the ASCII table, and so I modified the command a bit, and cast the numbers to characters. The revised command is shown here (remember the % symbol is an alias for the ForEach-Object cmdlet. The [char] casts the number to a System.Char .NET Framework type).
65..90 | % { [char]$_ }
These commands and their associated output are shown in the following image.
Trick # 9 Get-AllHelpExamples
I am certain that you are familiar with using the Get-Help cmdlet. I use the Get-Help cmdlet on a regular basis. I can find Help about any cmdlet or function by supplying the name of the cmdlet or function as an argument as shown here.
Get-Help Get-Service
One thing that is pretty cool is that I can also use an alias for the argument as shown here.
Get-Help gsv
If I need to see a complete list of Help for a particular cmdlet, I use the Full switched parameter. Because this will generate a lot of text, when I am in the Windows PowerShell console, I can pipe the results to the pager as shown here.
Get-Help gsv –full | more
The pager displays one page of text at a time, and halts with a More prompt. Pressing the space bar will cause it to advance to the next page of text. If I know that I will use the full display, I use the Help function. That’s right, Help is a function, not an alias. What the help function does is incorporate the pager. Therefore, the following two commands are equivalent.
Get-Help gsv –full | more
Help gsv -full
One of my favorite tricks involves pairing the Get-Command cmdlet and the Get-Help cmdlet together. I get a list of all the cmdlets on a system, pipe them to the Get-Help cmdlet, and view the examples. It is rather cool. But, instead of calling Get-Help with the Examples parameter, I reference the MamlCommandHelpInfo object and retrieve the Examples property. It is cool. Here is the command I like to use.
Get-Command -CommandType cmdlet | % { (get-help $_.name).examples }
Trick #10 Converting WMI Dates
One of the things people like to complain about with WMI is the way that dates are displayed. I can agree with them…to an extent. An example of a WMI date is shown here. Note that the first four characters are the year, followed by two for the month and two for the day. If you hold your head sideways and squint, you might be able to read the date without too much problem.
PS C:\> (gwmi win32_operatingsystem).installdate
20110604220039.000000-240
So the format is a bit strange…that is not too bad. What is a real pain is that it is not a System.DateTime object, rather it is a plain old string. This makes calculations based on dates a bit cumbersome.
PS C:\> (gwmi win32_operatingsystem).installdate.gettype()
IsPublic IsSerial Name BaseType
——– ——– —- ——–
True True String System.Object
In the old days, the Scripting Guys wrote a function that was included in the ScriptOMatic. This function would parse the string and convert it into some sort of intelligible format. In Windows XP, WMI introduced a method to convert the string into a date, but it was rather difficult to use, and most people did not know about it anyway—so they continued to use the Scripting Guys function.
When Windows PowerShell 1.0 came out, I was overjoyed to find the ConvertToDateTime method built onto the WMI object. For example, if I want to convert the install date into a regular date, I store the WMI object in a variable, and then call the ConvertToDateTime function while passing it the InstallDate property. This is shown here.
PS C:\> $os = gwmi win32_operatingsystem
PS C:\> $os.ConvertToDateTime($os.installDate)
Saturday, June 04, 2011 10:00:39 PM
More than just translating the date, it actually converts the object into a real System.DateTime object. This is shown here.
PS C:\> ($os.ConvertToDateTime($os.installDate)).gettype()
IsPublic IsSerial Name BaseType
——– ——– —- ——–
True True DateTime System.ValueType
Because I have an actual DateTime object, I can use it to perform date calculations. For example, if I want to see how long the operating system has been installed, I pass InstallDate to the New-TimeSpan cmdlet as shown here.
PS C:\> new-Timespan $os.ConvertToDateTime($os.installDate)
Days : 2
Hours : 20
Minutes : 51
Seconds : 31
Milliseconds : 174
Ticks : 2478911740086
TotalDays : 2.86911081028472
TotalHours : 68.8586594468333
TotalMinutes : 4131.51956681
TotalSeconds : 247891.1740086
TotalMilliseconds : 247891174.0086
This concludes my top ten Windows PowerShell Tricks. This list is accurate as of today. I learn new things about Windows PowerShell every single day, and so this list is likely to change over time. If you happen to see me somewhere and you want an easy way to start a conversation, just ask me what cool things I have learned about Windows PowerShell recently. I guarantee that will get me talking—getting me to shut up, well, that is a different story.
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