Using PSObject to store data in PowerShell
When writing PowerShell scripts, I often search for specific data, store that data in an object and then most times I export it to CSV format. This article shows you how to do all of this using PSObject
.
The easiest way I find to store data for an object is to store it using a PSObject
. If you have multiple objects you need to store data for then you can then store each PSObject
in an array. This array can then be exported to CSV.
A PSObject
is very much like a hashtable where data is stored in key-value pairs. You can create as many key-value pairs as you like for each PSObject
.
Creating a PSObject
As mentioned, the PowerShell PSObject
uses a key & value pair type structure. To store data in the PSObject
all you need to do is define a key and then store a value in the key. The examples below creates a new PSObject
and stores some data in the object. In this example we are creating two “keys” (Key1 and Key2). Each of these contain bits of data about the object (Value1 and Value2).
In a real-life scenario keys and values contain description type information about the object. So for example if we were storing information about a file, some of the key-value pairs we might create would be Name, FileExtension, Path, and Size.
Here is the how to create a PSObject
in both PowerShell 2.0 and 3.0 and above:
PowerShell 2.0
$MyPSObject = New-Object -TypeName psobject -Property @{
Key1 = 'Value1'
Key2 = 'Value2'
}
PowerShell 3.0 & above
In PowerShell 3.0 and above, it is recommended that you use the following code to create a PSObject
. This is because it maintains the order of each key value created, which means when exporting to CSV the sort order is maintained.
$MyPSObject = [PSCustomObject]@{
Key1 = 'Value1'
Key2 = 'Value2'
}
Storing multiple PSObjects in an array
So far we have looked at storing information about a single object (e.g. a file). What if we are enumerating a folder and need to store information about all the files in the folder? In that case, we would create a PSObject
for each file (to store its individual data) and then we would store all of these PSObjects in an array. This makes it really easy to store and export information for multiple objects.
Here is how you store a PSObject inside an array. To do this for multiple files you would just do this inside the ForEach
loop:
# Initialising the array
$MyArray = @()
# Storing PSObject in an array
$MyArray += $MyPSObject
An Real World Example
Let’s setup a quick example to help with the demonstration. In this example we are going to doing the following:
Reading a text file that has a list of employee names. For each name we will look them up in AD and gather some additional information, including username and email address. We will then be outputting this data to CSV.
Example Solution
The script below enumerates all of the employee names in the text file, and for each one searches AD for their additional employee information. Each of this data is stored in its own PSObject called $hItemDetails
.
To ensure the data is in the correct order when it is exported to CSV, we use the [PSCustomObject]@{}
method of creating a new PSObject
(only available in PowerShell 3.0 and above). Finally, as there are multiple employees, I store each PSObject in an array called $aResults
. This array is then exported to CSV.
Import-Module ActiveDirectory
$aResults = @()
$List = Get-Content "C:\Temp\List.txt"
ForEach ($Item in $List) {
$Item = $Item.Trim()
$User = Get-ADUser -Filter { displayName -like $Item -and SamAccountName -notlike "a-*" -and Enabled -eq $True } -Properties SamAccountName, GivenName, Surname, telephoneNumber
$sEmail = $User.GivenName + "." + $User.Surname + "@test.com"
$hItemDetails = [PSCustomObject]@ {
FullName = $Item
UserName = $User.SamAccountName
Email = $sEmail
Tel = $User.telephoneNumber
}
#Add data to array
$aResults += $hItemDetails
}
$aResults | Export-CSV "C:\Temp\Results.csv"
Hope this helps! Any questions or comments, let me know below.
Hello Luca,
What if I want to add another field to the pscustomobject?
I tried it like this:
$hItemDetails += @{“nickname” = “nickname for user”}
or
$hItemDetails += [pscustomobject]@{“nickname” = “nickname for user”}
But i got this error in both cases:
Method invocation failed because [System.Management.Automation.PSObject] does not contain a method named ‘op_Addition’.
thanks in advance for your help!
mariodeleon@gmail.com
Two years and no rely luca…
The error tells you the issue, there is no addition method for psobjects. You need to call add-member e.g. $psobject | Add-Member -MemberType NoteProperty -Name “Nickname” -Value “Gertrude”
$hitemDetails | Add-Member -Type NoteProperty -Name ‘nickname’ -Value $null
You can add another field by using add-member.
$hItemDetails | Add-Member -Type NoteProperty -Name ‘nickname’ -Value “nickname for user”
Excellent example, thanks!
Very cool. Thanks!
Thank you, massive help closing a gap I was struggling with.
Good One. Thanks
Now to add an array to a class…
How to append the results on the same row using new-object in powershell.
my sample results is look like this
Header1 Header2
Test
Yes
The results should be aligned to Test row
How to add an array of values to a single key,
for example:
$Properties = @{
SystemLog_Index = $EventLog_System_Last30Days_Error.Index
SystemLog_InstanceID=$EventLog_System_Last30Days_Error.InstanceID
SystemLog_Message= $EventLog_System_Last30Days_Error.Message
SystemLog_Time=$EventLog_System_Last30Days_Error.Time
SystemLog_EntryType=$EventLog_System_Last30Days_Error.EntryType
SystemLog_Source=$EventLog_System_Last30Days_Error.Source
}
$obj = New-Object PSObject -Property $Properties
$obj | Export-CSV
“The CSV does not able to show the array in its columns”
Luca, this was excellent-O! I have of late trying to do an EXPORT-CSV on a file that wasn’t an object. I saw other articles saying my fields needed to be properties in a object, etc. Very confusing, I was just getting the length property of each record in the .csv files. All said, this cleared everything up, excellent code example at the end. Thanks again!