What Formatting cmdlets do to your data

I have seen an increasing number of questions recently where the answer has been to remove Format-Table from the pipeline. As an example consider the names of the processes running on your machine

Get-Process -Name calc | Stop-Process

works because you are piping the selected object into the Stop-Process cmdlet.

Now think about this

Get-Process -Name calc | select Name | Stop-Process

a bit more long winded (the select isn’t necessary) but the resultant object hitting Stop-Process identifies a process by name which is all Stop-Process needs to work.

As a way to approach the reason for the first sentence in the post is there any difference between these two statements?

Get-Process -Name calc

Get-Process -Name calc | Format-Table

The output to screen looks identical. So  I should be able to do this:

Get-Process -Name calc | Format-Table | Stop-Process

What I get is a bunch of errors of the form:

Stop-Process : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.
At line:1 char:41
+ Get-Process -Name calc | Format-Table | Stop-Process
+                                         ~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (Microsoft.Power…FormatStartData:PSObject) [Stop-Process], ParameterB
    + FullyQualifiedErrorId : InputObjectNotBound,Microsoft.PowerShell.Commands.StopProcessCommand

The reason for this is simple.  The Format cmdlets destroy your pipeline and objects.  They take what they are given and output formatting directives. The only thing you can do with them is display them on screen (you can pipe to a text file but effectively the same thing)

If in doubt about what you’re dealing with at any time use Get-member

£> Get-Process | Get-Member

   TypeName: System.Diagnostics.Process

£> Get-Process | select name | Get-Member

   TypeName: Selected.System.Diagnostics.Process

Notice the slight change in that its now Selected.System.Diagnostics.Process instead of System.Diagnostics.Process

This only applies if you’re selecting a subset of properties. If you want the first N objects

£> Get-Process | select -First 5 | Get-Member

   TypeName: System.Diagnostics.Process

You still have the original type.

However, lets look at formatting

£> Get-Process | Format-Table | Get-Member

TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatStartData

TypeName: Microsoft.PowerShell.Commands.Internal.Format.GroupStartData

TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData

TypeName: Microsoft.PowerShell.Commands.Internal.Format.GroupEndData

TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatEndData


You get 5 different objects out – none of which have anything to do with your processes – apart from the values.

The Format cmdlets are designed to format your data for display. Thats all they do. Once your data hits the Format cmdlets that data can only be used fro display – nothing else. Put your Format cmdlets at the end of your pipeline and don’t attempt to do anything else with the data.

This entry was posted in Powershell Basics. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s