Creating Custom Objects in PowerShell from Scratch

Welcome back to our four-part series on creating custom objects in PowerShell! In part one, I discussed the basics of creating custom objects in PowerShell to meet your needs; however, in this version, we lost the original object. In part two, I showed you how to modify and create the custom object while retaining the original. Today we’ll learn how to create a custom object from scratch.

Later, in part four I’ll go deeper and include the enhancements found in PowerShell 3.0.

Creating Custom Objects Using Add-Member

First, let’s use Add-Member to create our objects.

​$obj=New-Object PSObject
$obj | Add-Member Noteproperty -Name Name -value "Jeff Hicks"
$obj | Add-Member Noteproperty -Name Memory -value ((Get-WMIObject
win32_computersystem).TotalPhysicalMemory/1gb -as [int])
$obj | Add-Member Noteproperty -Name Title -value "PowerShell Pro"
$obj | Add-Member Noteproperty -Name MVP -value $True
$obj | Add-Member Noteproperty -Name Blog -value http://jdhitsolutions.com/blog

I create an empty object and pipe it to Add-Member, adding new items. When I write $obj to the pipeline, I end up with this:

Sponsored Content

Passwords Haven’t Disappeared Yet

123456. Qwerty. Iloveyou. No, these are not exercises for people who are brand new to typing. Shockingly, they are among the most common passwords that end users choose in 2021. Research has found that the average business user must manually type out, or copy/paste, the credentials to 154 websites per month. We repeatedly got one question that surprised us: “Why would I ever trust a third party with control of my network?

​PS C:\> $obj

Name : Jeff Hicks
Memory : 8
Title : PowerShell Pro
MVP : True
Blog : http://jdhitsolutions.com/blog

This is a reasonable solution if you are gathering values to assign to your custom object throughout the script. I’ve also seen the following approach – which, although it does work, it is really more of a kludge.

​$obj = "" | Select Name,Memory,Title,MVP,Blog
$obj.Name="Jeff Hicks"
$obj.Memory=(Get-WMIObject win32_computersystem).TotalPhysicalMemory/1gb -as [int]
$obj.Title="PowerShell Pro"

Select-Object automatically creates the property names which are saved to $obj. You can then set each property. The end result is the same.

​PS C:\> $obj

Name : Jeff Hicks
Memory : 8
Title : PowerShell Pro
MVP : True
Blog : http://jdhitsolutions.com/blog

…well, almost. If I pipe the first example to Get-Member, my object type is System.Management.Automation.PSCustomObject. In the latter it is a Selected.System.String. Granted, this is a subtle distinction, but it could affect how items are formatted for display. It is possible to create your own formatting files and types, but that’s a whole ‘nother kettle of fish (or rather, series of articles). This second approach has some merits in an interactive session, but if you are creating custom objects in your scripts or functions, I think there is a better way to go about this in PowerShell 2.0.

Creating Custom PowerShell Objects Using New-Object

Since we’re talking about objects, let’s use a cmdlet that creates them: New-Object. You briefly saw this in the first example. With New-Object, you can create a blank custom object using the PSObject type. And while you could use the Add-Member technique, if you are only defining properties you can define them all at once by using a hash table, also known as an associative array.
You might start with something like this:

[email protected]{
Name="Jeff Hicks"
Memory=(Get-WMIObject win32_computersystem).TotalPhysicalMemory/1gb -as [int]
Title="PowerShell Pro"

If you put all the elements on one line, you will need to separate them with a semicolon. But because each entry is on its own line, PowerShell knows where to separate them. I typically use this technique collecting new property names. I can even add to the hash table.

$hash.Add("Book","PowerShell in Depth: An Administrator's Guide")

When I’m ready, I can call New-Object and use this hash table for all of my property values.

​New-Object -TypeName PSObject -Property $hash

This object is written to the pipeline.

​Help : http://bit.ly/AskJeffHicks
Name : Jeff Hicks
MVP : True
Book : PowerShell in Depth: An Administrator's Guide
Blog : http://jdhitsolutions.com/blog
Memory : 8
Title : PowerShell Pro

One potential downside in the second version is that you can’t predict in what order the properties will be displayed. You could create a custom format file, or if you’re in for really quick and dirty scripting, you could create something like this:

​New-Object -TypeName PSObject -Property $hash | Select Name,Title,MVP,Help,Book,Blog,Memory

In my example, I’m creating a one-off kind of object. But this approach works very well when working with objects in the pipeline.

​Function Get-SysInfo {



Process {
$os=Get-WmiObject Win32_OperatingSystem -ComputerName $computername
$cs=Get-WmiObject Win32_ComputerSystem -ComputerName $computername
$running=Get-Service -ComputerName $computername | where {$_.Status -eq "Running"}
$procs=Get-Process -ComputerName $computername

New-Object -TypeName PSObject -Property @{
System=("{0} {1}" -f $cs.Manufacturer.Trim(),$cs.Model.Trim())

} #close Process
} #close function

This function creates an entirely new object that pulls information from a variety of sources on a remote computer. Instead of creating a hash table in advance, I define one as the value for the –Property parameter. You can see the results of my efforts below in Figure 1.

Creating Custom Objects in Windows PowerShell
Figure 1: The custom object in action

This I can pipe to any other cmdlet, such as Export-CSV because it is an object. You can download Get-Sysinfo from the site.

Have I hit you over the head enough with my mantra that PowerShell is “all about the objects”? We’ll wrap up this series with part four, in which we’ll look at some new ways of creating objects in PowerShell 3.0.

Related Topics:

Live Webinar - Thursday, December 2nd! Active Directory Masterclass: AD Configuration Strategies for Stronger SecurityREGISTER NOW - Thursday, December 2, 2021 @ 1 pm ET

Active Directory (AD) is leveraged by over 90% of enterprises worldwide as the authentication and authorization hub of their IT infrastructure—but its inherent complexity leaves it prone to misconfigurations that can allow attackers to slip into your network and wreak havoc. 

Join this session with Microsoft MVP and MCT Sander Berkouwer, who will explore:

  • Whether you should upgrade your domain controllers to Windows Server
    2019 and beyond
  • Achieving mission impossible: updating DCs within 48 hours
  • How to disable legacy protocols and outdated compatibility options in
    Active Directory

Sponsored by: