Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to create custom objects.
Microsoft Scripting Guy, Ed Wilson, is here. Tonight is the PowerScripting PodCast. It is always a big deal around the Scripting House, because the Scripting Wife does all their scheduling for the crew and because of our shared interest in the Windows PowerShell community. Tonight will be a brilliant podcast (as they all are).
Note This is the third part of a three part series that talk about Windows PowerShell objects.
- In A PowerShell Object Lesson: Part 1, I talked about the advantage of using Windows PowerShell objects, and how they are helpful to the scripter.
- In A PowerShell Object Lesson: Part 2, I talked about pipelining objects.
Creating custom object in Windows PowerShell
One of the cool things to do with Windows PowerShell is to create a custom object. In fact, when I create a function, I normally return an object. I consider it a Windows PowerShell best practice that functions should return objects.
So how do I use Windows PowerShell to create objects? Surprisingly, it is easy. Very easy. What may not be so easy, is finding a good example on the Internet. (Of course, if you search for “PowerShell” and “create custom object” on the Hey, Scripting Guy! Blog, you will find over 300 topics).
The Windows PowerShell 1.0 way
It is a bit sad when I see people using Add-Member to create custom objects. This was the way I had to create custom objects in the Windows PowerShell 1.0 days. Now, this is all good in that Add-Member still works for creating objects, but it is a lot of work.
I think people search for “creating a custom object,” and they arrive at old code somewhere. It is also possible that people search for scripts, find an old script, see how the script creates the custom object, and adopt the technique. Like I said, this is fine. It works. Here is an example of using Add-Member to create a custom object:
myhost = $env:COMPUTERNAME
$date = (get-date).ToString()
$object = New-Object psobject
$object = Add-Member -InputObject $object -MemberType `
ScriptProperty -name host -value {$myhost} -PassThru
$object = Add-Member -InputObject $object -MemberType `
ScriptProperty -name date -Value {$date} -PassThru
$object
When I run the script, the output shown in the figure that follows appears in the output pane of the Windows PowerShell ISE.
When I pipe the $object variable to the Get-Member cmdlet, I see the following output:
PS C:\> $object | Get-Member
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
date ScriptProperty System.Object date {get=$date;}
host ScriptProperty System.Object host {get=$myhost;}
The Windows PowerShell 2.0 way
In Windows PowerShell 2.0, it became easier to create custom objects. This is because when I use the New-Object cmdlet, I can specify a hash table for the properties. I still use New-Object to create a new PSObject, but I now can specify the properties via the –Property parameter. I then create a hash table that assigns the property names and the property values.
$myhost = $env:COMPUTERNAME
$date = (get-date).ToString()
$object = New-Object psobject -Property @{
host = $myhost
date = $date }
$object
The script is several lines shorter, and it is a whole lot cleaner (no line continuation marks needed, and no–PassThru switches to confuse people). The command and its output are shown in the following image:
The command still creates a custom object. The members of the object are shown here:
PS C:\> $object | Get-Member
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
date NoteProperty System.String date=10/28/2013 5:53:03 PM
host NoteProperty System.String host=EDLT
The Windows PowerShell 3.0 way
In Windows PowerShell 3.0 (and this continues in Windows PowerShell 4.0), it is even easier to create custom objects. This is because we added a type accelerator, and therefore it is not necessary to use the New-Object command. I use the [PsCustomObject] type accelerator to cast a hash table that contains property names and values into a custom Windows PowerShell object.
This is by far, the cleanest way to create a custom object. The script is a bit shorter, and it is much more readable than the way I had to do things in the Windows PowerShell 2.0 world.
$myhost = $env:COMPUTERNAME
$date = (get-date).ToString()
$object = [pscustomobject]@{
host = $myhost
date = $date }
$object
The command and associated output are shown in the following image:
When I pipe the object to the Get-Member command, I see the following output:
PS C:\> $object | Get-Member
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
date NoteProperty System.String date=10/28/2013 6:04:06 PM
host NoteProperty System.String host=EDLT
Join me tomorrow when I have a guest blogger who will talk about Windows PowerShell and security.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy