Search code examples
powershellcustom-object

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


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
}

Solution

  • 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