Creating PowerShell Custom Objects

Whilst rarely needed when running PowerShell commands in the console, creating custom objects can be a useful technique when writing scripts or functions.  The typical use of custom objects is where you want to retrieve information from multiple sources and combine it for manipulation or display purposes.

There are several different ways that we can go about creating custom objects.  These include:

  • Abusing an existing object
  • Creating a PSCustom object
  • Creating a PSCustom object from a hash table
  • Build your own .NET class (PowerShell 5.0)

Abusing an Existing Object

The –Property parameter of Select-Object will allow you select the properties of an object to be used subsequently in the pipeline.  One use of this is to return fewer properties than were previously used, but if you specify a name of a property that does not exist, Select-Object will actually add a property with that name to the object.  String objects have few existing properties, so are a good choice for creating a custom object, an empty string probably being the best bet.

# Collect the data to be used in the custom object
$Comp = Get-CimInstance win32_computersystem
$OS = Get-CimInstance win32_operatingsystem
# Create the custom object
$MyCustomObject = "" |Select-Object `
  -Property Name, Domain, OS, Architecture
$MyCustomObject.Name = $Comp.Name
$MyCustomObject.Domain = $Comp.Domain
$MyCustomObject.OS = $OS.Caption
$MyCustomObject.Architecture = $OS.OSArchitecture

# Use the custom object
$MyCustomObject | Format-List
$MyCustomObject | Get-Member

Creating a PSCustom Object

A more formal way of creating an object is by using the New-Object and creating an object with the TypeName of PSCustomObject.  Once this object has been created, it can be piped to Add-Member cmdlets to add properties and their values.

# Collect the data to be used in the custom object
$Comp = Get-CimInstance win32_computersystem
$OS = Get-CimInstance win32_operatingsystem
 
# Create the custom object
$obj = New-Object -TypeName PSCustomObject
$obj | Add-Member -MemberType NoteProperty -Name Name -Value $Comp.Name
$obj | Add-Member -MemberType NoteProperty -Name Domain `
    -Value $Comp.Domain
$obj | Add-Member -MemberType NoteProperty -Name OS -Value $OS.Caption
$obj | Add-Member -MemberType NoteProperty -Name Architecture `
    -Value $OS.OSArchitecture
 
# Use the custom object
$obj | Format-List
$obj | Get-Member

Creating a PSCustom Object from a hash table

To use this method, first of all a hash table that is created where the required properties are stored as the Key-Value pairs.  Then, a new PSObject is created, but this time it uses the –Property parameter specifying the hash table.

# Collect the data to be used in the custom object
$Comp = Get-CimInstance win32_computersystem
$OS = Get-CimInstance win32_operatingsystem
 
# Create the hash table
$hash = @{Name=$Comp.Name;
          Domain=$Comp.Domain;
          OS=$OS.Caption;
          Architecture=$OS.OSArchitecture}
 
# Create the custom object
$objHash = New-Object -TypeName PSCustomObject -Property $hash
 
# Use the custom object
$objHash | Format-List
$objHash | Get-Member

Build your own .NET Class (Powershell 5.0)

PowerShell version 5.0 introduced the Class keyword that can be used to create a custom .NET class within your PowerShell session.  Once the class has been defined, an instance of that class can be instantiated with the .NET ‘New’ method.

# Collect the data to be used in the custom object
$Comp = Get-CimInstance win32_computersystem
$OS = Get-CimInstance win32_operatingsystem
 
# Create the .NET Class
class MyComp {
               [string]$Name;
               [string]$Domain;
               [string]$OS;
               [string]$Architecture;
}
 
# Create an object based on new class
$ClassObj = [MyComp]::new()
 
# Populate the properties
$ClassObj.Name = $Comp.Name
$ClassObj.Domain = $Comp.Domain
$ClassObj.OS = $OS.Caption
$ClassObj.Architecture = $OS.OSArchitecture
 
# Use the custom object
$ClassObj | Format-List
$ClassObj | Get-Member

As well as declaring property names, a class can also include methods and the ability to populate properties with values by passing parameters.  For example of these have a look at Trevor Sulivan’s blog post at http://trevorsullivan.net/2014/10/25/implementing-a-net-class-in-powershell-v5/