PowerShell

Getting Started with PSCustomObject in PowerShell

It has always been very easy to create hashtables and arrays in PowerShell, but there are times that a generic object comes in handy. Both hashtables and arrays are collections of objects, but a PSCustomObject is constructed of properties and values. PSCustomObject’s can be stored in arrays and hashtables, but ultimately they are intended to be a collection of properties.

When you need to store data in a structured format that can be extended upon, or in a more ordered fashion, PSCustomObject works great!

Creating a PSCustomObject in PowerShell

The fastest and easiest way to create a PSCustomObject is to use the following method, which works in all versions of PowerShell 3.0 and above.

$Object = [PSCustomObject]@{}

You can also use the New-Object -TypeName PSObject -Property @{} which will work in earlier versions of PowerShell, but it is also slower. This speed comes into play when you need to create or manipulate many objects in a script.

Sponsored Content

Maximize Value from Microsoft Defender

In this ebook, you’ll learn why Red Canary’s platform and expertise bring you the highest possible value from your Microsoft Defender for Endpoint investment, deployment, or migration.

You will notice that there appears to be a hashtable appended to the type declaration, [PSCustomObject], this is because we are passing the properties and values as key-values, best suited for a hashtable. The other benefit to this approach is that the PSCustomObject properties are ordered, unlike in a traditional hashtable where the keys will not maintain their initial order. Each of the created properties will be a NoteProperty like a typical PowerShell object.

Of course, we have created an empty PSCustomObject, which doesn’t do much good. How do we add properties? In the old days, we would use Add-Member to add properties to an existing object. There is an easier way, on initial object creation.

$Object = [PSCustomObject]@{
	'Property1' = 'Value1'
	'Property2' = 'Value2'
	'Property3' = 'Value3'
}

Great! We have properties now, but often in a script, you may need to add an additional property. This is where Add-Member is still handy. You can use this with PSCustomObject as seen below.

Add-Member -InputObject $Object -MemberType 'NoteProperty' -Name 'Property Space' -Value 'Value4'

Now that we have our custom object, read on to learn how to access the properties!

Returning Properties from a PSCustomObject

Just creating an object doesn’t do much good, so how do we go about retrieving the members? Just like any other typical PowerShell object, we can simply pass the name of the property using dot-notation to the object. There are three flexible ways to be aware of, as shown below.

# The standard way is to simply pass in the property name.
$Object.Property1
# Wrap the property name in quotes, single or double.
# This also allows you to return property names that have a space.
$Object.'Property1'
$Object.'Property Space'
# What if the property name is contained in a variable, pass that in too!
$Property = 'Property1'
$Object.$Property
# Bonus! If you use double-quotes, you can use variables within the name.
For($i = 1; $i -LT 5; $i++) {
  $Object."Property$i"
}

As you can see from above, there are a lot of ways that we can address a property using PSCustomObject. What else can we do with our PSCustomObject? To find out, read on!

Extending our PSCustomObject

Ok, so now that we have a basic object what can we do with it? Since this is a standard PowerShell object, we have the ability to use more than just a NoteProperty on the object. Most of the time you will just use the key-value pair that is a NoteProperty, but we can actually extend the object to use an evaluated ScriptBlock every time the object is accessed. Let’s create a new object with two properties, one that is a NoteProperty and the second, which is a ScriptBlock that just returns the output from Get-Date.

# Add a Scriptblock using the type accelerator of [ScriptBlock]{}.
# Wrap that declaration and code in parenthesis to then run the method of InvokeReturnAsIs().
# By using this method, you make sure to return just the output, not further encapsulated.
$Object = [PSCustomObject]@{
	'Property1' = 'Value1'
	'DateTime'  = ([ScriptBlock]{
    Get-Date
  }).InvokeReturnAsIs()
}

You may notice on subsequent runs that the value of DateTime is not updating. That is because the output is evaluated on the creation of the object. If we want to have this code dynamically evaluated we need an actual ScriptProperty member type. To do this, we need to use Add-Member as shown in the following.

Add-Member -InputObject $Object -MemberType ScriptProperty -Name "DateTimeDynamic" -Value { Get-Date }

As you can see from the above code, each time the code is run the DateTimeDynamic is evaluated and returned.

Bonus! Returning a Function as a Property

Even cooler is the ability to return a function as a property! Simply assign the function to a property name and it will run and store the value in the memory of the object the first time it is run.

Function Get-FormattedDateTime {
  Get-Date -Format "yyyyMMdd_hhmmss"
}

$Object = [PSCustomObject]@{
  'DateTimeFormatted' = Get-FormattedDateTime
}

Conclusion

As you can see, PSCustomObject is incredibly useful. There are many possibilities that the object unlocks, especially with the ScriptBlock and ScriptProperty methods. With the ability to evaluate a function as a value as well, you can easily extend the object in to unique use cases. Explore PSCustomObject and see how it can be added to your scripts today!

Related Topics:

BECOME A PETRI MEMBER:

Don't have a login but want to join the conversation? Sign up for a Petri Account

Register
Comments (0)

Leave a Reply

Entrepreneur, hustler, husband, dad, Automator, content producer, published author, Microsoft MVP, DevOps pro and passionate problem-solver.
External Sharing and Guest User Access in Microsoft 365 and Teams

This eBook will dive into policy considerations you need to make when creating and managing guest user access to your Teams network, as well as the different layers of guest access and the common challenges that accompany a more complicated Microsoft 365 infrastructure.

You will learn:

  • Who should be allowed to be invited as a guest?
  • What type of guests should be able to access files in SharePoint and OneDrive?
  • How should guests be offboarded?
  • How should you determine who has access to sensitive information in your environment?

Sponsored by:

 
Live Webinar: Active Directory Security: What Needs Immediate Priority!Live on Tuesday, October 12th at 1 PM ET

Attacks on Active Directory are at an all-time high. Companies that are not taking heed are being punished, both monetarily and with loss of production.

In this webinar, you will learn:

  • How to prioritize vulnerability management
  • What attackers are leveraging to breach organizations
  • Where Active Directory security needs immediate attention
  • Overall strategy to secure your environment and keep it secured

Sponsored by: