- Table of Contents
- Introduction to the Reference Guide
- The New Itinerary for Windows Server 2008
- The Registry
- Domain Organization
- Executing the Migration Plan
- Resource Management
- Security
- Networking at the Link Level
- Network Applications
- Windows Management Instrumentation
- The Dawn of Windows Server 2008
- Windows Server By Command
- PowerShell: The Once and Future Command Line
- The Three-Dimensional Command Prompt
- Home Instantiation for Fun and Profit
- The Application Object versus the Automation Object
- How PowerShell's Math Breaks Down
- Extending the Pipeline
- A Comparison of Operators
- To Be a PowerShell Script
- What a PowerShell Function Does
- Where Have All the Functions Gone? (Long Time Passing)
- The Automatic PowerShell/WMI Interface
- Evolving a Function Into a Script
- Precisely Formatting PowerShell Output for a Log File
Precisely Formatting PowerShell Output for a Log File
Last updated Nov 26, 2008.
Every PowerShell cmdlet outputs an object that is represented as a table. It may be a table of one item with one property label, but it’s still a table. For the sake of expediency, that table contains everything that falls within the criteria of the instruction, and if you didn’t specify any criteria, that means your table of everything could become extremely long. And even if you do use criteria to filter certain results, the amount of data that table returns may still be too much information for what you need.
Or put another way, PowerShell tables in their native formats don’t make great log file contents. More often, you’ll want to be able to disassemble a table so that your log file contains precisely the data you need.
Specifying Table Contents Column-by-Column
Back in the early days of Microsoft Level II BASIC for the TRS-80, there was an instruction called PRINT USING. Unlike the ordinary PRINT statement, it took a parameter that contained placeholder characters that represented the character position, on a monospaced display or printer page, where digits or letters would appear. In a more simplistic era of layout, it was the way you got all your columns to line up with one another.
That parameter for the PRINT USING statement was a string of alphanumeric characters. PowerShell borrows one more idea from the 1970s that works well in this context: For custom output, you create a string that acts as a template for where you want the output to appear. Since in the modern era we can refer to content elements by name, you don’t have to use placeholder characters to say “text goes here” or “digits go here.” Instead, you assemble the order of columns in the table, along with the custom labels you want attached above each column.
The way PowerShell goes about this is unique, but workable. Assume that there’s an input table containing data that PowerShell has already retrieved. Each column in that input table already has its own label. What you are formatting is an output table, and you’re creating a formatting string that maps the columns from the input table to the data in the output table.
Now, think of each column as a chain of elements, with each element separated by commas, that are assigned to an arbitrarily-named string variable, such as $table. Each element in that string is comprised of three properties:
- The Expression which maps to the value from the input table, perhaps adjusted or changed for the sake of the output table or perhaps left just the way it is;
- The Label which goes above each column that explains the meaning of each Expression;
- The Width of each column in evenly-spaced characters.
These property triplets are expressed within a pair of {curly braces}, with properties separated from each other by semicolons, with each enclosure preceded with a @ character, and with enclosures separated from one another by commas. It’s a tricky formation, as you’ll see, because it manages to embed curly braces within curly braces—a formation which, in other programming languages, means something else entirely.
The get-process command produces an extensive list of how much time and resources each active process in memory is using or has used already. For the sake of logging whether Windows Media Player has been running during a given time (a project begun in the previous segment), we may only want a running log to include a few of these elements: for instance, the amount of virtual memory consumed, the number of seconds of CPU time the process has already usurped, and the time in which the sample was processed—something the get-process table doesn’t actually contain. We don’t need to see the name of the process itself, since we’re only testing for Media Player.
The formatting string looks more like a pain to produce than it actually is. For this example, we only need three columns. Here’s how the string is generated:
$table = @{Expression={$_.VM};Label="Memory";Width=10},@{Expression={$_.CPU};Label="Uptime";Width=10}
Now, it may not be obvious from this instruction alone, but what you’re actually doing is creating a table. As you may have learned from earlier segments, a newly created PowerShell variable with an arbitrary name (like $table) takes the type of whatever you assign to it. This instruction actually creates a table with two rows (each @ enclosure is a row) and three columns. If you don’t believe me, you can ask PowerShell yourself:
PS C:\PowerShell> $table Name Value ---- ----- Label Memory Width 10 Expression $_.VM Label Uptime Width 10 Expression $_.CPU
The precise name for this type of generated table is a hash table. The table formatting template uses $_ as a placeholder to represent “this.” Obviously, there’s no “this” yet; but that’s okay, because PowerShell hasn’t processed the template yet. It will when you present the variable with the template as a parameter, with this instruction:
get-process | where {$_.ProcessName -match "wmplayer"} | format-table $table | '
out-file "mediaplayer.log" -append
The results of the initial get-process instruction are first filtered through the where clause, and then pared to size with the format-table cmdlet. That’s the cmdlet that uses the $table variable as a template. The result, for now, is attached to the end of the running log.
At this point, it’s not quite useful enough. What’s lacking is any mention of the time in which the measurement is taken. We can add that by adjusting the table template.
$table = @{Expression={$_.VM};Label="Memory";width=10},@{Expression={$_.CPU};label="Uptime";width=10}, '
@{Expression={get-date};Label="Time";width=24}
What that accomplishes is add a third column to the end:
Memory Uptime Time ------ ------ ---- 113012736 10.640625 11/16/2008 9:57:53 PM
Scheduling Automatic Script Runs
This may seem counter-intuitive, but for now, the principal way you get a PowerShell script to be executed periodically is outside of PowerShell—specifically, using Windows Task Scheduler.
First, you need to save your script (for our above example, all two instructions of it) in a text file with the extension .PS1. (After PowerShell version 2 comes out, certainly that will change.) Next, you write—of all things—a batch file that runs in the regular CMD.EXE command shell. Task Scheduler cannot yet automatically execute PowerShell scripts, so the next best thing it can do is run a DOS batch file that triggers PowerShell, and that in turn loads and executes the script.
Suppose our two-instruction script above was saved to a file called MPMonitor.PS1. Because PowerShell requires explicit references to script files for safety, you need to give a fully qualified patch to the file. So the batch file for running it might look like this:
Powershell.exe -command c:\psscripts\MPMonitor.PS1
You save that line as a batch file that Task Scheduler will recognize—for example, MPMonitor.BAT—and from there, you use Task Scheduler as you normally would to set up the batch file to run every hour or half-hour, or some reasonable interval.
Books and E-books
- Essential PowerShell, by Holger Schwichtenberg, Addison-Wesley Professional, 2008. Preview Associative Arrays (Hash Tables) from Chapter 6, The PowerShell Script Language, on Safari.
- Windows PowerShell Unleashed, by Tyson Kopczynski. Preview Chapter 10, Using PowerShell in the Real World, on Safari.
Online Resources
- Windows PowerShell Tip of the Week: Creating Custom Tables. Documentation from Microsoft TechNet.
- Windows PowerShell Owners’ Manual: Running PowerShell Scripts. Even more documentation from Microsoft TechNet.






Account Sign In
View your cart