Wednesday, September 19, 2018

Coloring in a HTML table for readablity.

When I first started doing health checks, I wanted to get the results to have some color.
I found a suggestion that the color codes could be added after. So I set up the testing script to put key words in the answers in the table and then after the table is converted to  HTML use a search and replace to substitute the HTML tags that would change the table color.

The first part is code from Microsoft that give the basic table design. 
The second part creates some headers and footers, and then creates the HTML table block for the message.
The Third part colors the table with HTML tags, using a replace command.
The final section assembles all the pieces into the final HTML document.



#HTML Header
$H = "<html>
    <style>
        BODY{background: # CAD3CC; font-family: Arial; font-size: 8pt;}
        H1{font-size: 16px;}
        H2{font-size: 10px;}
        H3{font-size: 12px;}
        H3.Pass{color: green}
        H3.Fail{color: red}
        TABLE{border: 1px solid black; border-collapse: collapse; font-size: 8pt;}
        TH{border: 1px solid black; background: #dddddd; padding: 5px; color: #000000;}
        TD{border: 1px solid black; padding: 5px; }
        td.Pass{background: #7FFF00;}
        td.Warn{background: #FFE600;}
        td.Fail{background: #FF0000; color: #ffffff;}
        </style>
    "


# Labels for HTML
$T = "<H1>Prod Application test</H1><BR>"
$B = $T + "<H2>Non-Prod Application test $Healhcheck " + $Warning + 
      "<H2><br> This is a test for Application servers <br><P> </H2> "
If ($E) { 
      $EReport = '<H1> <font color="red">ERROR REPORT:</H2></font><P><BR><BR> ' 
        }
$PostContent = "$EReport $E <BR>This report was generated on server $ENV:COMPUTERNAME <p>"
$DataReport = $Report | ConvertTo-Html -Fragment

#Crayon coloring code
#Coloring crayon the table.
$B += (($DataReport -replace "<td>Fail ", '<td class="Fail">') 
          -replace "<td>Pass ", '<td class="Pass">') 
          -replace "<td>Warn ", '<td class="Warn">'


#Now form the code into a final web page for emailing.


$Body = ConvertTo-Html -Head $H -Title $T -body $B -PreContent $PostContent



Start a scheduled task with a GUI menu.

Want to make a script run under other credentials?

You can create a scheduled task. Which can be fired off from a menu.

The menu script is below.
it takes advantage of the cool Out-GridView command.

$task = $true
While ($task)
{
    Write-host "Looking up available Healthchecks" -ForegroundColor Green
    Clear-Variable task
    Get-ScheduledTask -TaskPath "\AdminTasks\" |
    Select TaskName, State, Description |
    Out-GridView -OutputMode Multiple |
    foreach{
        if ($_)
        {
            $_ |
            Get-ScheduledTask |
            Tee-Object -Variable task |
            Start-ScheduledTask
            $task |
            Get-ScheduledTask
        }
    }
}


Wednesday, September 12, 2018

Parallel PowerShell - Part 3

Speaking of making code go faster...


I learned at the PowerShell Summit this year from Joshua King that doing repetitive tasks or loops one way may be quite a bit slower than doing it one way vs another. I learned that functions get compiled by the PowerShell engine, and don't continue to get interpreted.  I do recommend his presentation to understand how he did his research and validation. Whip Your Scripts into Shape: Optimizing PowerShell for Speed

This I had done without realizing the performance improvement is provided. It was chosen to work better with the Workflow process.

It appears that Workflows get compiled by the interpreter, and get the same speed up.  So these options are Good methods to speed things up. Workflows give the capability to run things in parallel.  Using functions within the workflow the method I used to use the parallel functions of Workflow and made the code easier to write and less restrictive. 

But back to my original story. 
One of the things I was concerned about was, what would happen if the server I tasked to do part of the testing, didn't respond for some reason. Would my Health Check crash? return a big red error? or worse. just stop dead and hang the script with no return. 
Fortunately, I haven't had a script zombie yet doing this in the parallel version of the script. But it was a plague in the previous versions. (a zombie is a script that never stops, waiting indefinitely. )
I did make sure to incorporate timeout settings on the web calls to ensure that the computer would not wait forever for a return. There were other checks that would get hung, so I made sure to verify the server was functioning properly before I ran those.  This seems to be where my scripts get stuck. 

The problem became running tasks in parallel, was what would happen if the server was off or nonresponsive. Fortunately, the parallel requests didn't hang like the previous versions. They did the opposite, they returned nothing.

So I had to devise a method to discover which tests had not returned. So I winced and then tried for a Jimmy Neutron brain blast...  that didn't work.
I tried things and came up with a loop that would check to see if each item in the original list of servers to test was in the results.

One approach was to review the errors in the shell variable  $ERROR.  but that didn't work out in some cases.
So to get a full picture, I found that comparing the list of servers submitted with the resulting Responses.


$Missing = $Servers | ?{ $result.PSComputerName -notcontains $_ }


So this gives us the ability to create some additional entries of the response to mark the missing responses.

$MissingServers = $Missing | foreach {
    $MissingServer = @{
        "URI"               = "https://$($_):443/App/Service.svc?wsdl";
        "StatusCode"        = "Fail 00";
        "StatusDescription" = "Fail N/A";
        "Result1"           = "N/A";
        "Result2"           = "N/A s"
        }
    New-Object -TypeName PSObject -Property $MissingServer
    } #Close foreach

So you can combine your results and get a complete table with :

$Result += $MissingServers

Where $Result is the results of the successful test.