Home > front end >  Merging objects with different properties
Merging objects with different properties

Time:12-01

I'm trying to loop through a CSV containing a list of computers and related services. the first ForEach loops through each 'row'. Then I split the contents of the Services 'column' and loop through the array using a foreach.

The result is:

Computer   winrm            webclient
--------   -----            ---------
localhost1 result goes here result goes here
localhost2
localhost3

I want the result to be like this:

Computer   winrm            webclient    soundservice     netlogon    www     someservice
--------   -----            ---------   ------------       -------     ----     -------
localhost1 running          stopped
localhost2                               running          running    running
localhost3                                                                      running

The problem seems to be that for the second ForEach, it creates a different object each time, and when it comes to adding the object to an objectarray, it only shorts the results from the first object. How can I 'merge' the different objects as it goes through each loop?

function Get-ServiceStatus {

    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$False)]
        [string] $ServiceListPath                               # Specifies this accepts an array of strings
    )


    BEGIN {
        # $Csv = Import-Csv $ServiceListPath

$CSVListTemp = @"
Computer,services
localhost1,winrm;webclient
localhost2,soundservice;netlogon;www
localhost3,someservice
"@

        $Csv = $CSVListTemp | ConvertFrom-CSV
        $ObjArray = @()
    }


    PROCESS {
        
        ForEach ($Row in $Csv) {

            write-host $Row.Computer -ForegroundColor Green

            # $obj = @()
            $obj = new-object psobject
            $obj | add-member -name Computer -type noteproperty -value $Row.Computer

            $ServiceList = $Row.Services -split';'
            #write-host "SERVICELIST: $ServiceList"
    
                ForEach ($Service in $ServiceList) {
                    write-host "$($Service)" -ForegroundColor cyan
                    $obj | add-member -name $Service -type noteproperty -value "result goes here"
                    
                }

            $ObjArray  =$obj 

        } #End of first ForEach 
        Return $objarray 
    } # End of Process
}

Get-ServiceStatus

CodePudding user response:

Iterate over the underlying properties of each object via the hidden psobject memberset. This way you can discover all possible property names, remove duplicates, and then pipe to Select-Object:

# fetch data
$statusObjects = Get-ServiceStatus

# discover property names
$uniqueNames = $statusObjects |ForEach-Object {
    $_.psobject.Properties.GetEnumerator() |ForEach-Object Name
} |Sort-Object -Unique

# select all possible properties from all objects
$statusObjects |Select $uniqueNames

CodePudding user response:

If you want to rewrite your function to get that desired output this should get you started:

$csv = @"
Computer,services
localhost1,winrm;webclient
localhost2,soundservice;netlogon;www
localhost3,someservice
"@ | ConvertFrom-Csv

$definedColumns = $csv.Services.Split(';') | Select-Object -Unique

$obj = foreach($line in $csv)
{
    $tmp = [ordered]@{
        Computer = $line.Computer
    }
    $serv = $line.Services.Split(';')

    foreach($service in $definedColumns)
    {
        $tmp[$service] = (
            'Not Found', # => Change this to $null to get the exact output
            'Running'
        )[[int]($service -in $serv)]
    }

    [pscustomobject]$tmp
}

$obj | Format-Table -AutoSize
Computer   winrm     webclient soundservice netlogon  www       someservice
--------   -----     --------- ------------ --------  ---       -----------
localhost1 Running   Running   Not Found    Not Found Not Found Not Found
localhost2 Not Found Not Found Running      Running   Running   Not Found
localhost3 Not Found Not Found Not Found    Not Found Not Found Running
  • Related