In-depth: PowerShell Out-GridView cmdlet

Been digging into the internals of the PowerShell CmdLet Out-GridView, Almost reverse engineering how the feature works.

Background

Out-GridView is essentially a wrapper around the Microsoft .NET DataGridView Windows Form Control. As long as we can translate the PowerShell data into a form that the DataGridView can display, DataGridView will do most of the work for us.
DataGridView is quite powerfull, able to handle display for a wide range of data types, string, arrays, and can natively handle XML data types.

Display Modes and Inputs

Out-GridView has several display modes:

  • Non-Blocking ( no wait *Default* ) – Display the data in the Out-GridView window and immediately return, allows the script to continue running.
  • Blocking ( -Wait ) – Display the data in the Out-GridView window and wait until the
  • Single ( -OutputMode Single ) – Display the data in the Out-GridView window. User can select one line, and the entry is returned as the object in the pipeline (equivalent to the -PassThru switch)
  • Multiple ( -OutputMode Multiple) – Display the data in the Out-GridView window. User can select one or more lines, and the selected entries are returned as results in the pipeline.

In addition to the mode, there is also an option to change the title.

Data

Passing data into Out-GridView is very easy, just pass in via the pipeline:

get-process |out-gridview

The -InputObject parameter accepts pipeline input, now you would think that we could also just pass the output as a parameter, like this:

out-gridview -inputobject (get-process)

However, Out-GridView doesn’t like that, it treats any data passed in as a parameter as a single object and displays as a single line in the Out-GridView window. Which is confirmed by the online help for Out-GridView:

-InputObject 
Accepts input for Out-GridView.

When you use the InputObject parameter to send a collection (more than one) 
of objects to Out-GridView, Out-GridView treats the collection as one 
collection object, and it displays one row that represents the collection.  
To display the each object in the collection, use a pipeline operator (|) 
to send objects to Out-GridView.

There is one exception to this rule, is that if you pass in a C# IDictionary collection (PowerShell HashTable), as a parameter, Out-GridView will parse that input as multiple objects:


$g = @{} ; get-process | %{ $g.Add($_.ID,$_.Name) } ; out-gridview -inputobject $g

I personally don’t like the way Out-GridView does this, and if I had to change the default behavior I force the enumeration of arrays.

Formatting

Additionally, PowerShell has some extensive support for advanced formatting that the DataGridView does not understand, so we need to help DataGridView understand which fields to use in the display. Out-GridView appears to display the same columns and data as the “Format-Table” shows, so it’s a matter of extracting out that data.

If we were to run the command “Get-ChildItem -file” and view the output using the “Get-Member” cmdlet we can see that it outputs the Type “System.IO.FileInfo”


PS C:\> get-childitem -file | gm

TypeName: System.IO.FileInfo

Name MemberType Definition
---- ---------- ----------
Mode CodeProperty System.String Mode{get=Mode;}
AppendText Method System.IO.StreamWriter AppendText()
...

We can then use the "get-FormatData" cmdlet to get a list of different formatting types associated with the selected type:


PS C:\> (get-formatdata System.Diagnostics.Process).formatviewDefinition

Name Control
---- -------
children TableControl
children ListControl
children WideControl

If we can dig further into the formatting information to get a list of Columns and formatting data for each row.

However, it's important to note that sometimes the Row data can contain PowerShell Code, so we may need to call *Back* to our PowerShell environment to parse and get the correct data.


PS C:\> $(get-formatdata System.Diagnostics.Process).formatviewDefinition. `
Control[0].Rows.Columns.DisplayEntry.Value

HandleCount
[long]($_.NPM / 1024)
[long]($_.PM / 1024)
[long]($_.WS / 1024)
[long]($_.VM / 1048576)

if ($_.CPU -ne $())
{
$_.CPU.ToString("N")
}

Id
ProcessName

Now we have the information to display PowerShell data in a structured graphical way!

-k

Advertisements

One thought on “In-depth: PowerShell Out-GridView cmdlet

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