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