Sending output to CSV and HTML
On the screen the output is great, but there are many times when you need to share your results with other people. When looking at sharing information, you want to choose a format that is easy to view and interpret. You might also want a format that is easy to manipulate and change.
Comma Separated Values (CSV) files allow the user to take the output you generate and use it easily within a spreadsheet software. This allows you the ability to compare the results from vSphere versus internal tracking databases or other systems easily to find differences. It can also be useful to compare against service contracts for physical hosts as examples.
HTML is a great choice for displaying information for reading, but not manipulation. Since e-mails can be in an HTML format, converting the output from PowerCLI (or PowerShell) into an e-mail is an easy way to assemble an e-mail to other areas of the business.
What's even better about these cmdlets is the ease of use. If you have a data object in PowerCLI, all that you need to do is pipe that data object into the ConvertTo-CSV
or ConvertTo-HTML
cmdlets and you instantly get the formatted data. You might not be satisfied with the HTML-generated version alone, but like any other HTML, you can transform the look and formatting of the HTML using CSS by adding a header.
In this recipe, you will examine the conversion cmdlets with a simple set of Get-
cmdlets. You will also take a look at trimming results using the Select
statements and formatting HTML results with CSS.
This recipe will pull a list of virtual machines and their basic properties to send to a manager who can reconcile it against internal records or system monitoring. It will export to a CSV file that will be attached to the e-mail and you will use the HTML to format a list in an e-mail to send to the manager.
Getting ready
To begin this recipe, you will need to use the PowerShell ISE.
How to do it…
In order to examine the conversion cmdlets using Get-
cmdlets, trim results using the Select
statements, and format HTML results with CSS, perform the following steps:
- Open the PowerShell ISE and run
Add-PSSnapIn
VMware.VimAutomation.Core
to initialize a PowerCLI session within the ISE. - Again, you will use the
Get-VM
cmdlet as the base for this recipe. The fields that we care about are the name of the VM, the number of CPUs, the amount of memory, and the description:$VMs = Get-VM | Select Name, NumCPU, MemoryGB, Description
- In addition to the top-level data, you also want to provide the IP address, hostname, and the operating system. These are all available from the
ExtensionData.Guest
property:$VMs = Get-VM | Select Name, NumCPU, MemoryGB, Description, @{N="Hostname";E={$_.ExtensionData.Guest.HostName}}, @{N="IP";E={$_.ExtensionData.Guest.IPAddress}}, @{N="OS";E={$_.ExtensionData.Guest.GuestFullName}}
- The next step is to take this data and format it to be sent as an HTML e-mail. Converting the information to HTML is actually easy. Pipe the variable you created with the data into
ConvertTo-HTML
and store in a new variable. You will need to reuse the data to convert it to a CSV file to attach:$HTMLBody = $VMs | ConvertTo-HTML
- If you were to output the contents of
$HTMLBody
, you will see that it is very plain, inheriting the defaults of the browser or e-mail program used to display it. To dress this up, you need to define some basic CSS to add some style for the<body>
,<table>
,<tr>
,<td>
, and<th>
tags. You can add this by running theConvertTo-HTML
cmdlet again with the-PreContent
parameter:$css = "<style> body { font-family: Verdana, sans-serif; font-size: 14px; color: #666; background: #FFF; } table{ width:100%; border-collapse:collapse; } table td, table th { border:1px solid #333; padding: 4px; } table th { text-align:left; padding: 4px; background-color:#BBB; color:#FFF;} </style>" $HTMLBody = $VMs | ConvertTo-HTML -PreContent $css
- It might also be nice to add the date and time generated to the end of the file. You can use the
-PostContent
parameter to add this:$HTMLBody = $VMs | ConvertTo-HTML -PreContent $css -PostContent "<div><strong>Generated:</strong> $(Get-Date)</div>"
- Now, you have the HTML body of your message. To take the same data from
$VMs
and save it to a CSV file that you can use, you will need a writable directory, and a good choice is to use yourMy Documents
folder. You can obtain this using an environment variable:$tempdir = [environment]::getfolderpath("mydocuments")
- Now that you have a temp directory, you can perform your export. Pipe
$VMs
toExport-CSV
and specify the path and filename:$VMs | Export-CSV $tempdir\VM_Inventory.csv
- At this point, you are ready to assemble an e-mail and send it along with your attachment. Most of the cmdlets are straightforward. You set up a
$msg
variable that is aMailMessage
object. You create anAttachment
object and populate it with your temporary filename and then create an SMTP server with the server name:$msg = New-Object Net.Mail.MailMessage $attachment = new-object Net.Mail.Attachment("$tempdir\VM_Inventory.csv") $smtpServer = New-Object Net.Mail.SmtpClient("hostname")
- You set the
From
,To
, andSubject
parameters of the message variable. All of these are set with dot notation on the$msg
variable:$msg.From = "fromaddress@yourcompany.com" $msg.To.Add("admin@yourcompany.com") $msg.Subject = "Weekly VM Report"
- You set the body you created earlier, as
$HTMLBody
, but you need to run it throughOut-String
to convert any other data types to a pure string for e-mailing. This prevents an error whereSystem.String[]
appears instead of your content in part of the output:$msg.Body = $HTMLBody | Out-String
- You need to take the attachment and add it to the message:
$msg.Attachments.Add($attachment)
- You need to set the message to an HTML format; otherwise, the HTML will be sent as plain text and not displayed as an HTML message:
$msg.IsBodyHtml = $true
- Finally, you are ready to send the message using the
$smtpServer
variable that contains the mail server object. Pass in the$msg
variable to the server object using theSend
method and it transmits the message via SMTP to the mail server:$smtpServer.Send($msg)
- Don't forget to clean up the temporary CSV file you generated. To do this, use the PowerShell
Remove-Item
cmdlet that will remove the file from the filesystem. Add a-Confirm
parameter to suppress any prompts:Remove-Item $tempdir\VM_Inventory.csv -Confirm:$false
How it works…
Most of this recipe relies on native PowerShell and less on the PowerCLI portions of the language. This is the beauty of PowerCLI. Since it is based on PowerShell and only an extension, you lose none of the functions of PowerShell, a very powerful set of commands in its own right.
The ConvertTo-HTML
cmdlet is very easy to use. It requires no parameters to produce HTML, but the HTML it produces isn't the most legible if you display it. However, a bit of CSS goes a long way to improve the look of the output. Add some colors and style to the table and it becomes a really easy and quick way to format a mail message of data to be sent to a manager on a weekly basis.
The Export-CSV
cmdlet lets you take the data returned by a cmdlet and convert that into an editable format for use. You can place this onto a file share for use or you can e-mail it along, as you did in this recipe.
In the earlier chapters, you didn't go into much detail on how to create a mail message. This recipe takes you step by step through the process of creating a mail message, formatting it in HTML, and making sure that it's relayed as an HTML message. You also looked at how to attach a file. To send a mail, you define a mail server as an object and store it in a variable for reuse. You create a message object and store it in a variable and then set all of the appropriate configuration on the message. For an attachment, you create a third object and define a file to be attached. That is set as a property on the message object and then finally, the message object is sent using the server object.
There's more…
ConvertTo-HTML
is just one of four conversion cmdlets in PowerShell. In addition to ConvertTo-HTML
, you can convert data objects into XML. ConvertTo-JSON
allows you to convert a data object into an XML format specific for web applications. ConvertTo-CSV
is identical to Export-CSV
except that it doesn't save the content immediately to a defined file. If you had a use case to manipulate the CSV before saving it, such as stripping the double quotes or making other alternations to the contents, you can use ConvertTo-CSV
and then save it to a file at a later point in your script.