Home > Uncategorized > PowerShell: Dynamically Color PosH Generated HTML. – Part 1

PowerShell: Dynamically Color PosH Generated HTML. – Part 1

PowerShell is excellent at dumping data into HTML tables.  We can gather ‘fragments’ of tabled data and combine these tables into a web page to create very complex reports. With PowerShell tools we can do this almost effortlessly and with little knowledge of HTML.  So why is this not used more often?  How come we keep seeing scripters generating hand gathered html written line by line into a file?

The best way to manage HTML is through the DOM (Document Object Model).  In IE we can access the DOM through the ‘window.document’ object.  Why not just load the document into IE and create or modify reports?

There are issues with doing this. Besides being cumbersome it does not play well when the script is run unattended under the Task Scheduler.  We also may only want to set a color or two then send the HTML as an email.  IE is overkill in most cases.

PowerShell has the ConvertTo-Html CmdLet which can do many things including generating fragments and combining fragments into a page.Here is a link to a great two-part article on how to generate HTML multi-table reports:

http://blogs.technet.com/b/heyscriptingguy/archive/2012/06/04/powershell-in-depth-part-1.aspx
http://blogs.technet.com/b/heyscriptingguy/archive/2012/06/04/powershell-in-depth-part-2.aspx

The strength in the above-linked approach is that it allows us to gather all manner of data into simple tables and throw them onto a page.  The page display can be modified via the injected CSS with one drawback.  If we need to send the HTML by email much of the power of CSS2 will be lost as most email HTML supports only a subset of CSS1.

Here are a couple of simple ideas and techniques that can help to extend the usefulness of the PowerShell HTML CmdLet.

  1. Use the XML DOM to edit the HTML fragment.
  2. Add an ID to each table fragment which will allow you to control the style of individual tables independently.
  3. Use XPath to select rows and set color based on the row’s value.

Here are the techniques to accomplish the above items.

Load HTML Fragment into XML DOM
# get some data for demo and generate a fragment
$html=gwmi win32_logicaldisk |
Select-Object deviceid,@{N='PercentFree';E={[math]::Round($_.Freespace/$_.Size * 100,0)}} |
ConvertTo-Html -Fragment
# load HTML into XML DOM
$xml=[xml]$html

That’s it. Just generate the output to the HTML converter and capture in a variable.  Send the variable through the XML type accelerator and save it in the variable $xml.

But you are thinking it is HTML and not XML right?  Well it is really HTML. PowerShell generates XHTML compliant HTML which is also XML.  While we cannot load a full page because of the ‘DOCTYPE’ header line we can load a fragment because it is raw and legal XML.

The HTML we just loaded looks like this:

<table>
<colgroup>
<col/>
<col/>
</colgroup>
<tr><th>deviceid</th><th>PercentFree</th></tr>
<tr><td>A:</td><td></td></tr>
<tr><td>C:</td><td>3</td></tr>
<tr><td>D:</td><td></td></tr>
<tr><td>E:</td><td>87</td></tr>
<tr><td>F:</td><td>89</td></tr>
</table>

Perfectly legitimate XML because all tags are closed correctly and there is no conflicting DOC header.

Now we can modify the HTML very easily using out XML editing tools.

Add an ID to the Table

First let’s put an ID on the table. We will call the table id=”diskTbl”.  To add an ID we need to add an attribute to the table tag and set its value.  We do this by using the XML CreateAttribute method.

$attr=$xml.CreateAttribute(‘id’)

$attr.Value=’diskTbl’

Next we get the table tag and append the new attribute.

$xml.table.Attributes.Append($attr)

That is it.  The table now has an attribute called ‘id’ with our value.  Want to see?

<table id="diskTbl"><colgroup><col /><col /></colgroup><tr><th>deviceid</th><th>PercentFree</th></tr><tr><td>A:</td><td
></td></tr><tr><td>C:</td><td>3</td></tr><tr><td>D:</td><td></td></tr><tr><td>E:</td><td>87</td></tr><tr><td>F:</td><td
>89</td></tr></table>

See.  The attribute gets nicely tucked into the table tag and no playing with messy strings and broken HTML.  Ok.  The HTML is no longer ‘pretty’ printing.  We can fix that later.  HTML and XML don’t care what they look like so we can change it around using our XML Stream Writer later.

So boys and girls, that is the story of how to manipulate HTML in the DOM.  You can now add a tag “id” into your CSS and make every table a different color.

Add Other Attributes The Same Way

#diskTbl { background-color: blue; }

You could also use the technique to add a class attribute and add multiple cascading classes to your table.

$attr=$xml.CreateAttribute('class')
$attr.Value=’red box wrap’

Now our CSS can look like this:

,red { background-color: red; }

.blue {…. }

.box { border-collapse: collapse; border-style: solid; border-width: 1px; }

.nobox {…..}

.wrap { ….}

.nowrap {….}

Using that technique we can add additive styles to an object from a general purpose style sheet.  Now ConvertTo-Html is becoming potentially very useful.

We can use the returned html to send an HTML mail message

Send Colorized Email With PowerShell
$html=gwmi win32_logicaldisk | 
Select-Object deviceid,@{N='PercentFree';E={[math]::Round($_.Freespace/$_.Size * 100,0)}} |
ConvertTo-Html -Fragment
$xml=[xml]$html
$attr=$xml.CreateAttribute('id')
$attr.Value=’diskTbl’
$xml.table.Attributes.Append($attr)
$html=$xml.OuterXml|Out-String
$style='<style type=text/css>#diskTbl { background-color: blue; }</style>'
$body=ConvertTo-Html -head $style -body $html -Title "Disk Usage Report"|Out-String
$msg=@{
To=$to
From=$from
Subject="Disk usage report for $([datetime]::Now)"
BodyAsHTML=$true
Body=$body
}
Send-MailMessage @msg

Of course this only shows one table but, if we can color one, we can color as many as we like.  The important thing is that we can set style elements for individual table.  We can also add additive style for convenience.  We have also done this without dumping to and from a file and without playing with strings.

More?

How about coloring individual lines?  Can we use this to set a lines color depending on the value of a column? Of course.  Next time I will show how easy it is to do that although I have already given you almost all of the pieces for doing it.  We just need about three more lines of code and some knowledge about how XML works and how to make HTML do some of the work for us.

Part 2: https://jvierra.wordpress.com/2012/07/23/powershell-dynamically-color-posh-generated-htmlpart-2/

Advertisements
Categories: Uncategorized

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: