jerkdavi
jerkdavi

Reputation: 47

powershell color output if matches condition

Firstly, I have a csv file with a list of programs that should be included with the default installation of Windows. The CSV looks like this.

Name;Version;Vendor;InstallDate
64 Bit HP CIO Components Installer;18.2.4;Hewlett-Packard;20210902
7-Zip 18.05 (x64 edition);18.05.00.0;Igor Pavlov;20210812
Adobe Acrobat Reader DC;20.006.20034;Adobe Systems Incorporated;20210903

Secondly, I have a powershell script that tries to compare the list of programs on a remote computer with the list of programs in the CSV file (by Name, Version and Vendor). It is supposed to output only the non matching programs.

The comparing part works perfectly, but now I would like to color the lines of output which match by Name and Vendor, but not by Version. How would I go about doing that?

This is my powershell script.

$programs =@()
$programs = Get-WmiObject –computername <ComputerName> -Class Win32_Product
foreach($program in $programs) {
    foreach($defprogram in Import-Csv -Path "...\defprograms.csv" -Delimiter ';') {
        if ($program.Name -eq $defprogram.Name -And $program.Version -eq $defprogram.Version -And $program.Vendor -eq $defprogram.Vendor) {
            $programs = $programs -ne $program }
    }}
$programs | sort-object Name | format-table -AutoSize Name,Version,Vendor,InstallDate

And this is the output of fore mentioned script.

In the example in the output, I would like to make the '64 Bit HP CIO Components Installer' colored red.

64 Bit HP CIO Components Installer                      15.2.1         Hewlett-Packard       20210909
Canon Laser Printer/Scanner/Fax Extended Survey Program 2.1.2          CANON INC.            20210216

Upvotes: 1

Views: 1295

Answers (2)

Theo
Theo

Reputation: 61208

You can do this by reading the CSV with default programs you need to colorize.
Then create a regex string of their .Name property. Use Format-Table as usual, but append Out-String -Stream so you can capture the resulting lines in a variable

# your code here:
$programs = @(Get-WmiObject –computername <ComputerName> -Class Win32_Product)
foreach($program in $programs) {
    foreach($defprogram in Import-Csv -Path "...\defprograms.csv" -Delimiter ';') {
        if ($program.Name -eq $defprogram.Name -And $program.Version -eq $defprogram.Version -And $program.Vendor -eq $defprogram.Vendor) {
            $programs = $programs -ne $program }
    }
}

# read the default programs and create a regex string of their Name fields
$defprograms = Import-Csv -Path "...\defprograms.csv" -Delimiter ';'
$redprograms = '({0})' -f (($defprograms.Name | ForEach-Object { [regex]::Escape($_) }) -join '|')

# Format-Table the array of objects and capture the resulting lines in variable `$table`
$table = $programs | Sort-Object Name | Format-Table -AutoSize Name,Version,Vendor,InstallDate | Out-String -Stream
# next loop through these lines and find lines that match any of the default program names
switch -Regex ($table) {
    "^$redprograms\s*" { 
        Write-Host $_.Substring(0, $matches[1].Length) -NoNewline -ForegroundColor Red
        Write-Host $_.Substring($matches[1].Length)
    }
    default { $_ }
}

Output would then look something like

enter image description here

Upvotes: 1

JPBlanc
JPBlanc

Reputation: 72680

Not a nice solution, but do the job :

$a = @"
Name;Version;Vendor;InstallDate
64 Bit HP CIO Components Installer;18.2.4;Hewlett-Packard;20210902
7-Zip 18.05 (x64 edition);18.05.00.0;Igor Pavlov;20210812
Adobe Acrobat Reader DC;20.006.20034;Adobe Systems Incorporated;20210903
"@

$b = $a | Convertfrom-Csv -Delimiter ';'

$b | % {Write-Host "$($_.name);" -ForegroundColor Red -NoNewline;  Write-Host "$($_.Vendor);" -NoNewline; Write-Host $($_.Installdate) ;}

Upvotes: 2

Related Questions