Prof. Powershell

The PowerShell Blacksmith Part 6: Accessorizing Your Tool

In this installment of the PowerShell Blacksmith, Jeffrey Hicks will show you how to format values.

As part of your PowerShell toolmaking apprenticeship, we're going to take a field trip of sorts and visit some related examples of accessorizing your tool or even tools from others. If you recall when we started this journey, I made a reference to formatting values like Sum (from Measure-Object or my own Measure-Data) as KB, MB or GB. One way to accomplish this is to use Select-Object with a custom hash table.

PS C:\> dir c:\work -file | Measure-Object length -sum | Select Count,@{Name="SizeMB";Expression={$_.sum/1mb}}

Count                                             SizeMB
-----                                             ------
260                                   242.623012542725

But that can get tedious if you always want this value in MB. One way to accomplish this is by adding your own type extension. In PowerShell 3.0 this is much easier because no don't have to deal with complicated XML files and you can make the change on the fly.

To modify the result from Measure-Object, we first need to know the object type. If you pipe a Measure-Object expression to Get-Member you'll see that it is a Microsoft.PowerShell.Commands.GenericMeasureInfo object. I'm going to add a new property called SumMB. The value will be calculated from a scriptblock. Instead of using $_, we use $this.

$MB = {
#$this is current object
$this.sum/1MB
}

To make it easier to follow, I'll use a hash table or parameters to splat to Update-TypeData.

$paramHash= @{
TypeName = "Microsoft.PowerShell.Commands.GenericMeasureInfo"
MemberType = "ScriptProperty"
MemberName = "SumMB"
Value = $MB
}

The hash table keys are the same as parameter names for Update-TypeData. I'll update the type information for the current session.

Update-TypeData @paramHash

If this is something I wanted all the time I'd add these lines to my PowerShell profile. I won't see the new property.

PS C:\> get-process chrome | measure WS -sum

Count    : 12
Average  :
Sum      : 334774272
Maximum  :
Minimum  :
Property : WS
SumMB    : 319.265625

And there it is! But what if I want to use this with my new Measure-Data tool. If you pipe the results of Measure-Data command I see that it is a custom object. But lots of things are custom objects in PowerShell so I can't make a blanket type update.

What I can do however, is define my own custom type name. Here' the relevant revised code:

… Write-Verbose "Creating a custom object"
$obj = New-Object -TypeName PSobject -Property $hash

    #insert a custom type name
    Write-Verbose "Inserting custom type name"
    $obj.PSObject.TypeNames.Insert(0,'Prof.PowerShell.DataMeasure')

    #write result object to pipeline
Write-Verbose "Writing result to the pipeline"
$obj
#endregion
} #close end

The name can be whatever you want. Here you can see the result.

[Click on image for larger view.] Figure 1.

With a type name, I can now use Update-TypeData.

$paramHash= @{
TypeName = "Prof.PowerShell.DataMeasure"
MemberType = "ScriptProperty"
MemberName = "SumMB"
Value = {$this.sum/1MB}
}

Update-TypeData @paramHash

Let's see what happens:

PS C:\> 1200KB,3458KB,9807KB | measure-data

Sum     : 14812160
Average : 4937386.66666667
Median  : 3540992
Range   : 8813568
Minimum : 1228800
Maximum : 10042368
SumMB   : 14.1259765625

It works, but SumMB is a special case and not something I need to see all the time. So the last step is to customize the default display when I run Measure-Data. This is accomplished by modifying the default display property set.

Update-TypeData -TypeName $typename -DefaultDisplayPropertySet Sum,Average,Median,Range,Minimum,Maximum

Now watch what happens:

[Click on image for larger view.] Figure 2.

I get the default display, but if I also want the sum in MB, I have that as well. To make this a permanent part of my tool, I can insert the Update-TypeData lines at the end of the script file for the function. You can download the updated script file here (https://app.box.com/s/uiztdd6krq7wux7iq5km).

I could do something similar for Average, Minimum and Maximum for my tool or even Measure-Object. But I'll show you an another way next time.

About the Author

Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at Petri.com, and a frequent speaker at technology conferences and user groups.

comments powered by Disqus
Most   Popular