PSCustomObjects are an essential part of PowerShell’s toolkit. PowerShell being a scripting language needed to provide users (mainly admins) ability to create objects for purposes like creating excel reports. Hashtable’s alone did not provide the flexibility like exporting to csv.
Why PSCustomObject
Being part of .net and Object Oriented programming paradigms ideally we need a class to create an object. I have covered this topic briefly here. PowerShell targeted for admins didn’t want users to create complex class and object structures for scripting tasks. Through PSCustomObject, PowerShell gave its users ability to create objects on the fly. If needed PowerShell does provide option to create a class.
PSCustomObject is mainly used when a custom object needs to be created which has information from two or more commands. For example,
$services = Get-Service # command 1 with service information
$date = Get-date # command 2 with today's date
# you want to create an excel report with today's date or some other information from another command like domain name.
# PSCustomObject can help to create that new object which has data from both $services and $date variable.
# This new object can then be exported as a csv report
Creating PSCustomObject
PSCustomObject can be created using few ways. Previously we used New-Object
cmdlet as mentioned in this Microsoft doc.
More concise and commonly used method is to use the [PSCustomObject]
as below. Using below structure, objects can be created with properties and methods as well. Generally for reporting objects will only have properties as in example below.

PSCustomObject Internals
Internally PowerShell uses hashtables to store properties and methods created from a PSCustomObject. A hashtable is a data structure that stores data as key-value pairs. Each key is unique within the hashtable and is used to retrieve its associated value. In a sense its a glorified hashtable in that, general hashtable don’t have format or export csv options built-in.
You can easily add or remove properties from a PSCustomObject to adapt it to your specific needs. This flexibility allows you to extend the object’s functionality.
PSCustomObject Example 1
A simple example of creating an object from date and disk.
$date = Get-Date # command 1
$disk = Get-Disk # command 2
$diskInfo = [PSCustomObject]@{
date = $date
diskSize = [math]::Round($disk.Size / 1GB, 2)
}
$diskInfo # object which can now be exported
PSCustomObject Example 2
Below is an example of which, say you have a list of computers and want to get process info of all the machines. Script below can run and get a csv for all machines.
Each line of the excel needs be an object. While creating script, think of the output and construct PSCustomObject in accordance to that.
$date = Get-Date # Getting date
$processes = Get-Process # Getting all processes
$computerName = Get-WmiObject -Class Win32_ComputerSystem # Getting Computer info
$processInfo = @(); #Initilizing the object
foreach ($process in $processes) { # Going through each process and creating that object line after line for each process
$processInfo += [PSCustomObject]@{
date = $date
computerName = $computerName.name
processId = $process.Id
processName = $process.Name
}
}
$processInfo | Export-Csv filename.csv