Alex
Alex

Reputation: 13

How do I format the output of my multidimensional array with colors based on the value?

I'm using a Powershell script to pull a list of servers in an Active Directory domain, poll them to determine if the SMTP-Server role is installed, and then output that list to the display in several ways.

I want to format the output of the script to use colors based on the values.

I'm creating a custom PSObject with the output, which consists of two properties simply named "Name" and "IsInstalled". Name is a string field and IsInstalled is a Boolean value. I want both values to display red if the IsInstalled value is False, and to display green if it's True.

import-module ServerManager
import-module ActiveDirectory

$Computers = Get-ADComputer -Filter {(OperatingSystem -like "*windows*server*") -and (OperatingSystem -notlike "*2003*") -and (Enabled -eq "True")} -Properties Name,OperatingSystem | Select Name | Sort-Object -Property Name #| Select-Object -First 5
$Present = ""
$YesCount = $null
$Results = @()
$Count = 0

ForEach ($Computer in $Computers)
    {
        $Name = $Computer.Name
        $SMTP = Get-WindowsFeature "smtp-server"
        $IsInstalled = $null
        if($SMTP.Installed)
            {
            Write-host "SMTP is installed on $Name"
            $Present = "True"
            $IsInstalled = $True
            $YesCount++
            }
        else
            {
            Write-host "Not on $Name"
            $IsInstalled = $False
            }
        $object = New-Object -TypeName PSObject
        $object | Add-Member -MemberType NoteProperty -Name Name -Value $Name
        $object | Add-Member -MemberType NoteProperty -Name IsInstalled -Value $IsInstalled
        $Results += $object
        $Count++
    }

if (($Present = "True"))
    {
    Write-host ""
    Write-host "Checked $Count machines, and SMTP is installed on no servers!"
    }
else
    {
    Write-host "Checked $Count machines, and SMTP is installed on $YesCount servers!"
    }
$Results |Select Name,IsInstalled | Sort-Object Name | Format-Table -AutoSize

I can use Sort-Object and Format-Table to control the output sorting and layout, but I can't figure out how to change the text color based on the value. Help?

Upvotes: 1

Views: 1683

Answers (2)

Theo
Theo

Reputation: 61178

In order to do this, you need to capture the output of Format-Table as a string array of data rows and output these rows in the color you want, depending on the IsInstalled property like this:

Change this last line of code:

$Results |Select Name,IsInstalled | Sort-Object Name | Format-Table -AutoSize

to this:

# format the data and split in into an array. Remove empty or whitespace-only entries
$rows = $Results | Sort-Object Name | Format-Table -AutoSize | Out-String -Stream | Where-Object { $_ -match '\S' }

# write the header and hyphen line below that from the table first
Write-Host
Write-Host $rows[0]
Write-Host $rows[1]

# next, write the data lines ($rows) in the appropriate color
for ($i = 2; $i -lt $rows.Count; $i++) {
    if ($Results[$i - 2].IsInstalled) {
        Write-Host $rows[$i] -ForegroundColor Green
    }
    else {
        Write-Host $rows[$i] -ForegroundColor Red
    }
} 

The output will look like

enter image description here

Upvotes: 1

Rich Moss
Rich Moss

Reputation: 2384

What an interesting question! You can use the color parameter to Write-Host, but that would only work for a full line of color, so it's not what you want.

Recent versions of the PowerShell console support VT100/ANSI escape sequences that you can embed in your string to colorize a substring. Here's a test to see if they're supported:

Write-Host "`e[35m RED `e[0m"

If not, there are some options described in this post.

To solve your problem, you can embed those escape sequences in a string representation of the IsInstalled property within each of your [PSObject] instances in $Results, and select that string rather than the boolean.

Upvotes: 0

Related Questions