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

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:

You can also specify -ComObject to create a COM Object, but that is not covered in this article.


#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 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 {[
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 {
    Function Sqr {
    Export-ModuleMember -Variable * -Function *}
$numbers.n1 = 5

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


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 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.


#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
#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
#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 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")

7 Resources

7.1 TechNet

7.2 Blog

See Also


Other Languages