PowerShell: Creating Custom Objects
Link to Parent: PowerShell - Deep Dive and Best Practice
Different Methods For Creating Custom Objects
1. New-Object
You can use the New-Object cmdlet to generate an object of any type. The two choices for custom objects are PSObject and Object
**
PSObject** creates an object of class System.Management.Automation.PSCustomObject
Object creates an object of class System.Object
While PSObject requires a bit more overhead, it is generally preferred. The drawbacks to Object are explained in this article:
http://cjoprey.wordpress.com/archived/custom-object-gotchas/
You can also specify -ComObject to create a COM Object, but that is not covered in this article.
Example:
#Example 1.1
$obj = new - object psobject
There are two different ways to add members to an object
1.1 Add-Member
The best (and most verbose) method is to use Add-Member. The reason for this is that you can specify the type of member to add (all other methods assume NoteProperty.
#Example 1.2
$obj = New-Object PSObject
Add-Member -InputObject $obj -MemberType NoteProperty -Name customproperty -Value ""
A note about this is that you need to specify a value where as with select-object you do not.
1.2 Hash
If you have a lot of properties to create and they all have values you can assign a hash table to the object to quickly create the objects properties. This can be very useful if you have a list of name/value pairs (return from a legacy command app or a text file)
Example
#Example 1.3
$props = @{
Property1 = 'one'
Property2 = 'two'
Property3 = 'three'
}
$object = new-object psobject -Property $props
1.3 Hash with V3
With V3 its a tad easier because they've added a type accelerator for the psobject which can be used like this.
#Example 1.4
$obj = [PSCustomObject]@{
Property1 = 'one'
Property2 = 'two'
Property3 = 'three'
}
2. New-Module -AsCustomObject
You can also use New-Module with the AsCustomObject parameter to create a custom object. The main advantage to this is the ability to type constrain a member. It is also easier to add methods (functions)
#Example 2.1
$numbers = New-Module -AsCustomObject -ScriptBlock {[int]$n1=$null
Export-ModuleMember -Variable *}
$numbers.n1 = 4
$numbers.n1 = "abc"
If you test the above code you'll see that it will throw an error when you try to assign the string abc to it.
You can also use functions inside the scriptblock to act as methods for the object.
#example 2.2
$numbers = New-Module -AsCustomObject -ScriptBlock {
[int]$n1=$null
Function Sqr {
[math]::pow($n1,2)
}
Export-ModuleMember -Variable * -Function *}
$numbers.n1 = 5
$numbers.Sqr()
In this case forcing N1 to be a number allows you to write less validation code in the Sqr function.
3. Add-Type (C#)
In some rare cases the Add-Type cmdlet can be useful for creating a type by defining a class in C#. This provides you with a type name and access to the C# runtime. One of the main reasons to do this is to get access to the Win32_API calls.
#Example 3.1
Add-Type @"
using System;
public class myClass{
public Double number=0;
public Double Sqr()
{
return Math.Pow(number,2.0);
}
}
"@
$obj = New-Object myClass
$obj.number = 5
$obj.Sqr()
4. Select-Object
This method is great for a quick and dirty means of gathering data to be manipulated or filtered after the fact.
Example
#example 4.1
$obj = "" | select prop1, prop2
You are using a blank string as the base object and then assigning other properties to that object. The returned object type is a selected.system.string, however this can be updated to a custom typename by modifying the pstypenames code property.
#Example 4.2
$obj | gm
TypeName: Selected.System.String
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
prop1 NoteProperty prop1=null
prop2 NoteProperty prop2=null
You'll notice that the object type is a Selected.System.String.
5. Custom Types for Custom Objects
After creating a custom object, you can update the typename of the object to reference something else. This works great when using formatting files (.ps1xml) to change how the data is displayed for an object. This works with both using New-Object and the Select-Object methods described above.
The most common method of adding a typename is the Insert() method. This method allows you to insert the typename at a specified index of the collection. You can also use the Add() method, but this will add the typename at the bottom of the collection.
It is important to know that this will not add anything extra to the object, so you cannot turn an object into a hashtable with its associated methods just by inserting the hashtable typename into the object.
Examples:
**
**
#Example 5.1
#Create the custom object
$obj = "" | select prop1, prop2
#Update the typename to something else and place it at the first index of the collection
$obj.pstypenames.insert(0,'Custom.ObjectExample')
#Look at object
$obj | get-member
TypeName: Custom.ObjectExample
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
prop1 NoteProperty prop1=null
prop2 NoteProperty prop2=null
#Example 5.2
#Create custom object
$object = New-Object PSObject
#Add a custom typename to the object
$object.pstypenames.insert(0,'System.CustomObject.PSObject')
#Display object
$Object | Get-Member
TypeName: System.CustomObject.PSObject
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
6. Using Class (PowerShell v5 or higher)
This is a way to dynamically handle custom objects. Similar to add-type but a bit more flexible. You can instantiate the object, change its definition and then instantiate it again without having to start a new PowerShell instance.
Example
#Example 6.1
Class CustomObject{
[string] $Name;
CustomObject([string] $NameIn) {
$this.Name = $NameIn;
}
[string] JumbleName() {
$a = $null
[char[]]$this.Name| Sort-Object {Get-Random} | %{ $a = $PSItem + $a}
return $a
}
}
$x = [CustomObject]::new("aStringValue")
$x.JumbleName()
7 Resources
7.1 TechNet
7.2 Blog
- http://technet.microsoft.com/en-us/magazine/hh750381.aspx
- http://blogs.msdn.com/b/powershell/archive/2009/03/11/how-to-create-an-object-in-powershell.aspx
- http://mjolinor.wordpress.com/2011/10/08/new-object-from-a-hash-table-in-a-script-block/
- http://mjolinor.wordpress.com/2012/01/31/creating-objects-from-ordered-hash-tables-in-powershell-v3/
- http://learn-powershell.net/2010/09/19/custom-powershell-objects-and-performance/
- http://blogs.msdn.com/b/mediaandmicrocode/archive/2008/11/26/microcode-powershell-scripting-tricks-select-object-note-properties-vs-add-member-script-properties.aspx
- http://www.jonathanmedd.net/2011/09/powershell-v3-creating-objects-with-pscustomobject-its-fast.html
See Also