Creating Custom Objects in PowerShell : Introduction

Whenever I’m writing, speaking about, or training someone on PowerShell, I always stress that it is “all about the objects.” PowerShell is not about parsing or grep’ing text; it is about working with objects in the pipeline. Most of the time, you can simply reference objects that come from cmdlets such as Get-Service or Get-EventLog. But sometimes, especially when scripting, you may want to create your own custom objects. By writing scripts and functions that write objects to the pipeline, you can take advantage of PowerShell cmdlets like Sort-Object, Select-Object and Export-CSV.
This is a four-part series. Today I’ll discuss the basics of creating custom objects in PowerShell to meet your needs; however, in this version, we lose the original object. In part two, I’ll show you how to modify and create the custom object while retaining the original. Part three saw us learninghow to create a custom object from scratch. Finally, in part four, I’ll go deeper and include the enhancements found in PowerShell 3.0.

Creating a Custom Object from a Basic Object

You can use a number of techniques for creating a custom object. There’s not necessarily a “best” way except whatever best fits your objective. PowerShell 3.0 introduces some new techniques, but I’ll cover those another day.
First, let’s say you have a basic object from a cmdlet, and you simply want to add a custom property. The quick way is to pipe the object to Select-Object and use a special hash table to define a new property.

​PS C:\> get-wmiobject win32_operatingsystem |
>> Select @{Name="Computername";Expression={$_.CSName}},
>> Version,@{Name="OS";Expression={$_.Caption}},
>> @{Name="LastBoot";Expression={$_.ConvertToDateTime($_.LastBootUpTime)}}
>>
Computername version OS LastBoot
------------ ------- -- --------
SERENITY 6.1.7601 Microsoft Windows 7 U... 6/18/2012 1:09:27 PM


Because the WMI object has property names that aren’t always intuitive, I create a custom property. For example, I like using Computername as a property name since it is used all the time in PowerShell. But the Win32_OperatingSystem class doesn’t have that property — but it does have a property called CSName. So the first hash table tells PowerShell to create a key entry called “Computername” and assign it the value from the Expression scriptblock. In this case, I’m simply writing the CSName property of the current object (in this case, $_) in the pipeline. I do the same thing with Caption, renaming it OS.

The code in the Expression scriptblock can be as long as necessary. The original LastBootUpTime property is returned in a bulky, unfriendly format, like 20120618130927.610798-240. But all WMI objects in Powershell include an extra method called ConvertToDateTime.
The last property I’m defining, called LastBoot, invokes this method from the current object and converts the LastBootUpTime property, also of the current object. The end result of all of this is a custom object. I can verify by piping my command to Get-Member. You can see the results in Figure 1.
Fig 1: Create Custom Object
Figure 1: Get-Member shows the custom properties.
All that really matters is that I have a custom object with properties with which I can do something. For example, now I can run an expression like this:

​Get-wmiobject win32_operatingsystem -computername "serenity","quark","jdhit-dc01" | Select @{Name="Computername";Expression={$_.CSName}},Version, @{Name="OS";Expression={$_.Caption}},
@{Name="LastBoot";Expression={$_.ConvertToDateTime($_.LastBootUpTime)}} |
Sort LastBoot -Descending | format-table –autosize

I can use the “new” LastBoot property and sort it in descending order, as shown below.
Fig 2: Custom object in action
Figure 2: The custom object in action.
I use this technique all the time, particularly when I’m working interactively in the shell. However, as you can see, there’s a fair amount of typing involved. I no longer have the original Win32_OperatingSystem object, but in this case I don’t really need it. In the next post, I’ll show you another way to customize your objects and still retain the original.