Iterate through an array of powershell custom objects and output to html

e4rthdog picture e4rthdog · Jan 15, 2015 · Viewed 7k times · Source

I have an array :

$results =@()

Then i loop with custom logic through wmi and create custom objects that i add to the array like this:

$item= @{}
$item.freePercent = $freePercent
$item.freeGB = $freeGB
$item.system = $system
$item.disk = $disk
$results += $item

I know want to to some stuff on the results array, like converting to html .

I can do it with a foreach and custom html writing but i want to use convertto-html...

P.S. I can print out data like this but only this:.

foreach($result in $results) {
    $result.freeGB
}

Answer

Ansgar Wiechers picture Ansgar Wiechers · Jan 15, 2015

Custom object creation doesn't work like you seem to think. The code

$item= @{}
$item.freePercent = $freePercent
$item.freeGB = $freeGB
$item.system = $system
$item.disk = $disk

creates a hashtable, not a custom object, so you're building a list of hashtables.

Demonstration:

PS C:\> $results = @()
PS C:\> 1..3 | % {
>>   $item = @{}
>>   $item.A = $_ + 2
>>   $item.B = $_ - 5
>>   $results += $item
>> }
>>
PS C:\> $results

Name    Value
----    -----
A       3
B       -4
A       4
B       -3
A       5
B       -2

PS C:\> $results[0]

Name    Value
----    -----
A       3
B       -4

Change your object creation to this:

$item = New-Object -Type PSCustomObject -Property @{
          'freePercent' = $freePercent
          'freeGB'      = $freeGB
          'system'      = $system
          'disk'        = $disk
        }
$results += $item

so you get the desired list of objects:

PS C:\> $results = @()
PS C:\> 1..3 | % {
>>   $item = New-Object -Type PSCustomObject -Property @{
>>             'A' = $_ + 2
>>             'B' = $_ - 5
>>           v}
>>   $results += $item
>> }
>>
PS C:\> $results

  A     B
  -     -
  3    -4
  4    -3
  5    -2

PS C:\> $results[0]

  A     B
  -     -
  3    -4

Also, appending to an array in a loop is bound to perform poorly. It's better to just "echo" the objects inside the loop and assign the result to the list variable:

$results = foreach (...) {
             New-Object -Type PSCustomObject -Property @{
               'freePercent' = $freePercent
               'freeGB'      = $freeGB
               'system'      = $system
               'disk'        = $disk
             }
           }

Pipe $results into ConvertTo-Html to convert the list to an HTML page (use the parameter -Fragment if you want to create just an HTML table instead of an entire HTML page).

$results | ConvertTo-Html

An even better approach would be to pipeline your whole processing like this:

... | ForEach-Object {
  New-Object -Type PSCustomObject -Property @{
    'freePercent' = $freePercent
    'freeGB'      = $freeGB
    'system'      = $system
    'disk'        = $disk
  }
} | ConvertTo-Html