February 9th, 2010

Hey, Scripting Guy! How Do I Format with Windows PowerShell? (Part 2)

Bookmark and Share

(Note: Today’s article is written by guest scripter, Thomas Lee. Here is Thomas’ scripting autobiography from The Official Scripting Guys Forum! where he is a moderator: I’ve been scripting pretty much forever. I used to be pretty hot at JCL on the IBM 360 in the late 1960s, did a ton of shell scripting in the 70s on ICL VME. I learned batch scripting with DOS 2.0. I never really grokked VBS (and never got infected with *ix). But I truly “got” Monad when I first saw it in September 2003 and never looked back. I’m proficient in Windows PowerShell 1.0 and 2.0, and specialize in the .NET and WMI aspects. My one interesting fact is that I was the first person to blog about Monad. Check out my Under the Stairs blog and my PowerShell Scripts blog.

Part 2 is today. Part 1 was published yesterday. Thanks again, Thomas!)

———-

 

Formatting Strings Using the .NET Framework

Another approach to creating richer output is to build a nicely formatted string using the built-in formatting capability of the .NET Framework, and then use the Out-Host or similar cmdlet to get Windows PowerShell to display this string on the console. C# programmers are adept at doing this as the .NET Framework provides a wealth of rich formatting functions. The .NET Framework calls this composite formatting. It takes a list of objects and a composite formatting string and outputs nice formatting. The composite formatting string consists of some fixed text plus placeholders, which the Framework calls format items, which correspond to the objects in the list.

 

To see this in action, let’s start with a simple query: How many files are contained in the given folder? You can do this relatively easily like this:

(LS C:\FOO).count

You could assign a variable to this calculation, and then output that variable:

$Ccount = (LS C:\FOO).count

$Ccount

On my workstation, both these methods produce the number 67. Now if I just wanted this number, I could quit now, fully satisfied by the default formatting of the output. But if I were creating more structured bit output, I might want it nicely formatted in a string. Composite formatting to the rescue!

 

In Windows PowerShell, you use the -F operator (or -f if you prefer) to invoke the composite formatting feature in Windows PowerShell. The -F operator is really just a call to the Format() method of a string object, which is what does the actual formatting. You supply the composite format string that contains some predefined text and one or more placeholder, and the Framework will format the values you specify for those placeholders.

 

To illustrate this, try something like the following:

$Ccount = (LS C:\FOO\*.ps1).count

“There are {0} in C:\Foo” -f $ccount

Windows PowerShell takes the value on the right of the -F operator (which can be one or more variables or values) and into the composite formatting string. The format item is a value number enclosed in {} characters inside the composite formatting string. The placeholders tell the .NET Framework where to put each value. The first value (in the above case, $ccount) is formatted into placeholder {0}. If there were more values to format, the second is formatted into {1} and so on. The placeholders can be anywhere in the string:

$Ccount = (LS C:\FOO\*.ps1).count

$Today = Get-Date

“Today ({1}) there are {0} files in C:\Foo” -f $ccount,$today

You can also use the placeholder to tell Windows PowerShell how large the space is in which the value is placed and whether the value should be left-aligned or right-aligned within the space. To see this in operation, see the previous image, which shows some different ways to format the count of files.

Using the -F operator, you can create nicely formatted strings and then use these in output to the console. Suppose you wanted to send someone a count of e-mail messages in a mailbox. You could use Exchange EMS cmdlets to get the actual count of e-mail messages, and then use the -F operator to create a nicely formatted string that you send via e-mail.

 

The -F operator provides you with considerable formatting flexibility, and I use it a lot in my scripts. But there’s even more you can do to format strings, thanks to the .NET Framework. For more details about using the -F operator to format numbers, see this Windows PowerShell tip. And see this Windows PowerShell tip for more information about formatting date and time. For information about the composite formatting feature, see this article.

 

Using the .ToString() Method

In the .NET Framework, all objects have a .ToString() method that converts an object occurrence such as a specific file into a string. Though all objects have this method, the key is that each fundamental such as integers, real numbers, and strings all have a .ToString method. You can see this by trying:

$i=1

$i.tostring()

Of course, this doesn’t do all that much. After all, Windows PowerShell already uses the .ToString() method to output object types already. The real power in this method comes in the parameters you can pass to the .ToString() method. These provide even more detailed instructions about exactly how the .NET Framework is to format the value.

 

This is really useful when you calculate a value but you want to format a value as currency or as a percentage, or when you want to format large numbers with thousands separators and a fixed number of digits to the right of the decimal point. And of course you want to have the currency, thousands separators, and decimal points based on the current culture.

 

For a more detailed look at how the .NET Framework enables you to format any data you wish, see http://msdn.microsoft.com/en-us/library/fbxft59x.aspx. And fasten your seatbelt before you go there and put on protective head gear—your head might hurt! If you lack protective headgear, take a look at this post from the Windows PowerShell Team blog.

 

Using Hash Tables for More Complex Formatting

When you use Format-Table (or Format-List), you usually pipe some objects to the cmdlet and specify which properties you want to see. For example, to get just the name and size of a file, you could type:

Ls c:\foo\*.ps1 | format-table name, length -autosize

The length and name parameters passed to Format-Table are the names of two properties of the objects produced by the LS command. The LS command (okay, the Get-ChildItem cmdlet when run against the FileStore provider) produces both System.IO.FileInfo and System.IO.DirectoryInfo objects; however, in this example where we are looking for *ps1, only the former are produced.

 

In this example, we are passing Format-Table the names of two properties that are to be displayed. The call to Format-Table takes an array of names to format (although when you display more than 4-6 or so properties, the table tends to be a little unusable unless you have a very wide console window or very narrow columns). To provide more flexibility, Windows PowerShell also lets you pass hash tables to Fomat-Table and Format-List instead of property names. The hash table tells Windows PowerShell how to calculate and how to format a particular column (or row because you can also use hash tables when calling Format-List).

 

To show this in action, try the following:

$x1=@{label=”Process Name”;Expression={$_.name};alignment=”right”}

$x2=@{label=”CPU Used”;Expression={$_.CPU};FormatString=”N3″}

Get-Process notepad| Format-Table $x1,$x2 -autosize

In this case, we have created two hash tables ($x1 and $x2) and then call Format-Table specifying these hash tables. You can see the output in the following image. Both hash tables contain the label to be used for the column heading, the expression you use to calculate the value that Windows PowerShell displays. The first hash table includes how the column should be aligned; the second contains a .NET Framework format.

Image of formatting with hash tables


And of course, you can use both hash tables and values when calling either Format-Table or Format-List. For example try this:

$x3=@{label=”CPU Used”;Expression={$_.CPU};FormatString=”N4″}

Get-Process * | Format-Table name,$x3 -autosize

Then try this:

$x4=@{label=”CPU Time Used”;Expression={$_.CPU};FormatString=”N3″}

Get-Process * | Format-List name,$x4

 

Using hash tables with Format-List or Format-Table enables you to create nicely formatted output when you need it. For more details about hash tables and formatting, see this Windows PowerShell tip.

Summary

As we have seen in this article, Windows PowerShell has powerful default formatting. And when you want more, Windows PowerShell provides a wealth of formatting options including Format strings, the -F operator, and hash tables. You can even improve on the PS1XML files to create your own version of default formatting. We will leave the details of that to a future article. About the only limits are your own imagination.

 

Author

0 comments

Discussion are closed.