In regards to the differences between PSObject and PSCustomObject, as well as how they work, there is often some confusion.
Either approach can be used to take a set of values from a collection of PowerShell objects and collect them into a single output. Both avenues will also output the data as NoteProperties in the System.Management.Automation.PSCustomObject object types. What's the difference?
New-Object was introduced in PowerShell v1.0 and has undergone a number of changes while PSCustomObject was introduced in v3.0. New-Object must be used on systems running PowerShell v2.0 or earlier. From an administrative perspective, the main difference between version 2.0 and version 1.0 is the ability to use hash tables. For instance:
New PSObject in v1.0
"1
$Path = "c:\scripts"
2
$Directory = Get-Acl -Path $Path
3
4
ForEach ($Dir in $Directory.Access){
5
6
$DirPermissions = New-Object -TypeName PSObject
7
$DirPermissions | Add-Member -MemberType NoteProperty -Name Path -Value $Path
8
$DirPermissions | Add-Member -MemberType NoteProperty -Name Owner -Value $Directory.Owner
9
$DirPermissions | Add-Member -MemberType NoteProperty -Name Group -Value $Dir.IdentityReference
10
$DirPermissions | Add-Member -MemberType NoteProperty -Name AccessType -Value $Dir.AccessControlType
11
$DirPermissions | Add-Member -MemberType NoteProperty -Name Rights -Value $Dir.FileSystemRights
12
13
$DirPermissions
14
With the New-Object method in PowerShell v1.0, you have to declare the object type you want to create and add members to the collection in individual commands. This changed however in v2.0 with the ability to use hashtables:
New-Object in PS 2.0
"1
$Path = "c:\scripts"
2
$Directory = Get-Acl -Path $Path
3
4
ForEach ($Dir in $Directory.Access){
5
6
$DirPermissions = New-Object -TypeName PSObject -Property @{
7
8
'Path' = $Path
9
'Owner' = $Directory.Owner
10
'Group' = $Dir.IdentityReference
11
'AccessType' = $Dir.AccessControlType
12
'Rights' = $Dir.FileSystemRights
13
14
}
15
16
$DirPermissions
17
}"
Here's the output:
The script now looks much cleaner and saves a great deal of typing time. The downside of both methods is that the output may not be in the same order in which you listed it, so if you're looking for a particular format, it may not work. In addition to streamlining your scripts, PSCustomObject fixed this issue in v3.0.
PSCustomObject in PowerShell v3.0
"1
$Path = "c:\scripts"
2
$Directory = Get-Acl -Path $Path
3
4
ForEach ($Dir in $Directory.Access){
5
[PSCustomObject]@{
6
Path = $Path
7
Owner = $Directory.Owner
8
Group = $Dir.IdentityReference
9
AccessType = $Dir.AccessControlType
10
Rights = $Dir.FileSystemRights
11
}#EndPSCustomObject
12
}#EndForEach"
Your output will match what you have defined in your hashtable, as shown in the example. PSCustomObject also has the advantage of enumerating data faster than its New-Object equivalent. PSCustomObject can only be used on PSv2.0 and earlier systems.