YEMyslf
YEMyslf

Reputation: 447

How to dynamically add new properties to custom object in PowerShell

I have a custom object that contains device information that looks something like this.

name,model,sn
PC1,Elitebook 850, ABC123,
PC2,EliteDesk 600,123ABC

I have a function that retrieves threats detected by an antivirus product. These are returned as an array of objects. There are more properties than below but this is just an example

file,md5
bad.exe,adfdfdfd
evil.exe,fdfdffdf

I would like to add each member as properties to the custom object so the final output is similar to this.

name,model,sn,01_file,01_md5,02_file,02_md5

Currently, my script does this:

foreach($device in $devices){
    $threats = Get-Threats $device
    [pscustomobject] @{
        name = $device.device_name
        make = $device.make
        sn = $device.sn
        ThreatFileName = $threats.File -join ", "
        Threat_md5 = $threats.md5 -join ", "
    }
}

This works ok but I'd really like each object returned by the 'Get-Threats' function to be listed as its own set of properties. I need this to be generated dynamically because I don't know how many threats will be returned for each device.

Any thoughts on how to go about this?

Upvotes: 13

Views: 25529

Answers (2)

YEMyslf
YEMyslf

Reputation: 447

The answer from @krome got me pointed in the right direction although that answer wouldn't work for me as there could be multiple threats for each device.

I used the answer from @scobi on Dynamically get PSCustomObject property and values to arrive at this answer which meets my requirement that the new properties be generated dynamically.

foreach($device in $devices){
    $threats = Get-Threats $device
    if($null -ne $threats){
        $i = 1
        foreach($threat in $threats){
            $threat | Get-Member -MemberType NoteProperty | % Name | %{                
                Add-Member -InputObject $device -NotePropertyName ("Threat"+$i.ToString() + "_" + $_) -NotePropertyValue $threat.$_ -Force            
            }
            $i++
        }
    }
}
Write-Output $devices
  • I loop over each device in the devices array and call my Get-Threats function.
  • The if statement prevents the loop from running for any devices that don't have threats.
  • $i is used as my counter to increment the property name for each threat found so the properties will all have unique names
  • I then loop over each threat found piping to Get-Member to retrieve the property name and values
  • I use Add-Member to add additional properties for each threat found to each device in the loop, using the counter to give each propery a unique name

Upvotes: 3

Reese Krome
Reese Krome

Reputation: 313

You can add properties to objects at any time with the Add-Member cmdlet. Maybe start with an empty object and loop through the elements returned by Get-Threats, adding a member each time?

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/add-member?view=powershell-6

Edit: Example code to answer for reference.

$o = [pscustomobject]@{
    MemberA='aaa'
    MemberB='bbb'
    MemberC='ccc'
    MemberD='ddd'
}

"Before"
$o | ft

$o | Add-Member -MemberType NoteProperty -Name 'MemberE' -Value 'eee'
$o | Add-Member -MemberType NoteProperty -Name 'MemberF' -Value 'fff'

"After"
$o | ft

Upvotes: 19

Related Questions