Conditional formatting in psobject output

Welcome Forums General PowerShell Q&A Conditional formatting in psobject output

This topic contains 7 replies, has 3 voices, and was last updated by

 
Participant
4 years ago.

  • Author
    Posts
  • #15982

    Participant
    Points: 0
    Rank: Member

    Is there an elegant way to conditionally format psobject output to the console? I wrote a script to check if a specific service is running or stopped on a number of computers, and used IF logic and write-host -ForegroundColor to make the computers with the service Running stand out. I'm rewriting the script to output a psobject vs. using Write-Host , but am finding that I'm losing the coloring functionality.

  • #15984

    Keymaster
    Points: 1
    Rank: Member

    No. The formatting system is more or less color-blind, because it needs to work with more than just the console host. If you're okay with limiting yourself to the console for output, and you've named your script "Show-xxxxx" (the verb "Show" implying "this requires console visuals"), then Write-Host is the correct approach. Also understanding that the output of a "Show-xxxxx" script can only be displayed, and not piped to another command to sort, filter, export etc.

    You could consider an HTML-based report. My EnhancedHTML module lets you conditionally color table cells.

  • #15985

    Participant
    Points: 0
    Rank: Member

    Understood. I'll check out the EnhancedHTML module and look into integrating HTML output into my workflow.

  • #19313

    Participant
    Points: 0
    Rank: Member

    I am working with the EnhancedHTML module and it works really well. Thanks for this Don!

    I have an issue though where I am trying to modify some of the code to customize the results.

    In the demo, there is this line when showing bad services : $svcs = Get-WmiObject -class Win32_Service -ComputerName $ComputerName -Filter "StartMode='Auto' AND State'Running'"
    So I have taken out the filter because I want all of the services to show in the list and then modify them later.

    When I am modifying the values to format the table at the end, I have this in $params :

    'Properties'='Service Name',
    'Display Name',
    'Start Mode',
    @{n='State';e={$_.State};css={if (($_.State -eq "Stopped") -and ($_.StartMode -eq "Auto")) { 'red' } elseif ($_.State -eq "Running") { 'green' }}}}

    Everything works great except for the expression above. So what I am trying to do is if a service is running I change the font to green. If it is stopped and the startmode is auto, I want to make it red. The elseif condition for 'Running' is working and they are green. Nothing seems to happen with the condition for 'red' though. I am not sure what the issue might be either with the logic, syntax, or if this is just not possible.

    Any ideas?

    Todd

  • #19320

    Keymaster
    Points: 1
    Rank: Member

    That code will emit the "red" and "green" classes into the HTML. You have to define those classes in your CSS for it to have any visible effect.

  • #19323

    Participant
    Points: 0
    Rank: Member

    Thanks. I do have 'red' and 'green' defined in the CSS and both seem to work (instead of font color I am now using background-color to get the cells changed to make them more visible when scanning the list). There is something about : (b)if (($_.State -eq "Stopped") -and ($_.StartMode -eq "Auto")) { 'red' }(/b) that just never seems to work. It's the same code as what you had as the filter in the original function to get a bad service, but nothing in the cells that are shown that fit that condition is changed. I just remains a white cell with normal black text that says 'Stopped'.

    If I change it just to this (b)@{n='State';e={$_.State};css={if ($_.State -eq "Stopped") { 'red' } elseif ($_.State -eq "Running") { 'green' }}}}(/b) things work fine with all cells either red or green. That second condition though of (b)(-and ($_.StartMode -eq "Auto"))(/b) seems to make it stop working.

    Just not sure why this is. It looks like it should work to me.

    Also, as I was typing I thought about trying this with nesting if statements :

    (b)@{n='State';e={$_.State};css={if ($_.State -eq "Stopped") { if ($_.StartMode -eq "Auto") { 'red' }} elseif ($_.State -eq "Running") { 'green' }}}}(/b)

    That did not work either. Hmm.....

    Todd

  • #19349

    Keymaster
    Points: 1
    Rank: Member

    As a note, it's square brackets to do the formatting, not paren. You may need to do a shift+refresh in your browser to unload the old Javascript toolbar.

    It's possible my code isn't evaluating the more complex expression correctly. I'm not sure why; I basically just parse it as a script block. Possibly I'm not interpreting the double us of $_ correctly. Something I'll need to dig into at some point ;).

    As a workaround, the trick would be to add a property to your object.

    $services = get-service | foreach {
     if ($_.state -eq 'Stopped' -and $_.StartMode -eq 'Auto') { $_ | Add-Member NoteProperty Color 'red' } else { $_ | Add-Member NoteProperty Color 'green' }
    }
    

    You could then emit the "Color" property to the CSS:

    @{n='State';e={$_.State};css={$_.color}}

    Something vaguely like that. Point being, you don't want to have to use $_ twice in the CSS expression, since that isn't working, so you do the logic ahead of time and embed it in a custom property. I'd have to fuss a bit to see if the exact example here was the way to do it, but that's the approach I'd take.

  • #19426

    Participant
    Points: 0
    Rank: Member

    Many thanks for sticking with me on this Don. I fully understand what you are saying above and did finally get this to work using the principle. What I have below in the function that gets services now is a little different. Sorry, WAY too many years programming in Delphi with Object-Pascal. The syntax of PS is slightly different. 🙂

    It does do exactly what I need now though and I can move onto bigger fish. It could likely be cleaner and I can look at this once I finish the overall script. Appreciate the guidance!

        $WMISvc = Get-WmiObject -class Win32_Service -ComputerName $ComputerName
        foreach ($svc in $WMISvc) {
            
            #To add a color property to the newly created $props object to for conditional HTML cell formatting
            if ($svc.State -eq 'Stopped' -and $svc.StartMode -eq 'Auto') { $svccolor = 'red' } `
            elseif ($svc.State -eq 'Running') { $svccolor = 'green' } `
            else { $svccolor = '' }
    
            $props = @{'Service Name' = $svc.Name;
                       'Display Name' = $svc.DisplayName;
                       'Start Mode'= $svc.StartMode;
                       'State' = $svc.State;
                       'Color' = $svccolor}
            New-Object -TypeName PSObject -Property $props
        }
    

The topic ‘Conditional formatting in psobject output’ is closed to new replies.