How to add a custom property to a PowerShell array?
Solution 1
The answer to your question as stated would be to just use Add-Member
on the array object.
Add-Member -InputObject $sessions -MemberType NoteProperty -Name "State" -Value "Fabulous"
Adding a property to each element after you created the object is similar.
$sessions | ForEach-Object{
$_ | Add-Member -MemberType NoteProperty -Name "State" -Value "Fabulous"
}
This of course comes with a warning (that I forgot about). From comments
Beware, though, that appending to that array ($sessions += ...) will replace the array, thus removing the additional property.
Depending on your use case there are other options to get you want you want. You can save array elements into distinct variables:
# Check the current object state
$state = $object.Property .....
# Add to the appropriate array.
if($state -eq "Active"){
$activeSessions += $object
} else {
$inactiveSessions += $object
}
Or you could still store your state property and post process with Where-Object
as required:
# Process each inactive session
$sessions | Where-Object{$_.State -eq "Active"} | ForEach-Object{}
To avoid the destroying / recreating array issue, which can be a performance hog, you could also use an array list instead.
$myArray = New-Object System.Collections.ArrayList
Add-Member -InputObject $myArray -MemberType ScriptMethod -Name "NeverTellMeTheOdds" -Value {
$this | Where-Object{$_ % 2 -ne 0}
}
$myArray.AddRange(1..10)
$myArray.NeverTellMeTheOdds()
Notice that the array had its member added then we added its elements.
Solution 2
As Matt commented, you can use the Add-Member
on an enumerable type by supplying it as a positional argument to the -InputObject
parameter.
To allow for resizing after adding the new property, use a generic List
instead of @()
:
$list = [System.Collections.Generic.List[psobject]]::new()
$list.AddRange(@(
[pscustomobject]@{SessionId = 1; Active = $true}
[pscustomobject]@{SessionId = 2; Active = $false}
[pscustomobject]@{SessionId = 3; Active = $true}
) -as [psobject[]])
Add-Member -InputObject $list -MemberType ScriptProperty -Name ActiveSessionCount -Value {
return @($this |? Active -eq $true).Count
}
Now you can retrieve the active session count easily:
PS C:\> $list.ActiveSessionCount
2
FatalMerlin
Enthusiastic programmer, currently working as a Software Engineer for a multinational concern. Basic knowledge in a few programming languages and on all mayor OSs, but focussing on C# and TypeScript. Always willing to learn and participate!
Updated on June 18, 2022Comments
-
FatalMerlin almost 2 years
Say I have a PowerShell array
$Sessions = @()
which I am going to fill with PSCustomObjects. How can I add a custom property to the array itself? E.g. so I can have$Sessions.Count
which is built-in and$Sessions.Active
which I want to set to the active session count.I know that I can add properties to PSCustomObjects (in a dirty way) with
$MyCustomObject = "" | Select-Object Machine, UserName, SessionTime
but though doing so on an array would not result in the property being added.
So how can I achieve my goal? Is there any way to create a custom array?
-
Matt over 6 yearsI suggested an arraylist. We think alike it seems.