Solved

How to include a picture in an HTML Document using powershell

Posted on 2013-12-21
18
2,951 Views
Last Modified: 2014-01-11
I have an HTML document I am creating using powershell.  I am using convertto-html to create the document and now want to include a picture, but cannot figure out how to do that.

Can anyone help?
0
Comment
Question by:c7c4c7
  • 9
  • 8
18 Comments
 
LVL 70

Expert Comment

by:Chris Dent
ID: 39734620
Where will the image be located?

Are you hoping to e-mail it and embed the picture in the e-mail?

If it's a page on a web-server you would need either an absolute or relative path to the image in the HTML document. You cannot embed in HTML itself.

Chris
0
 

Author Comment

by:c7c4c7
ID: 39734803
I want the picture imbeded in the html.  The picture resides on a machine without a web server.
0
 

Author Comment

by:c7c4c7
ID: 39734911
The HTML report gets mailed to me, if I send the picture as well can I somehow display the picture in the HTML when it is opened?
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 39734936
Gotcha.

You can indeed, it's why I needed to know if you were e-mailing it.

You do so by attaching the image to the mail, then you need to reference that attachment in your HTML by content ID (<img src='cid:TheContentID />). You can set any sizing or other attributes as you need.

There are a lot of examples around, this is perhaps the best:

http://gallery.technet.microsoft.com/scriptcenter/Send-MailMessage-3a920a6d

Does the example make sense to you? I can elaborate on it if not.

Chris
0
 

Author Comment

by:c7c4c7
ID: 39735283
Sorry, I'm going to need some additional examples.  Also how do I make this work using the existing code I've all ready written using convertto-html, the HTML is generated automatically.  The example in the previous post looks like I have to write the HML myself, correct?

Thanks
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 39735591
Yes and no. You'll have to add something to the HTML to add the picture, but you don't have to write it all by yourself.

Where would you like the image to appear in your document?

And can you give an example of how you're generating it now?

Ideally if you can share your script that would work best, then I can show you how to put it together.

Chris
0
 

Author Comment

by:c7c4c7
ID: 39736409
Where would you like the image to appear in your document?
Towards the bottom of the report

And can you give an example of how you're generating it now?
Cut down version in the attachment

I want to remove the current memory useage part and include a more meaningful graph.  I will do the same thing for the driveinfo later on.  I'd like to keep them in the same position as they are now, down towards the bottom.
experts-exchange.txt
MemoryUseage.png
0
 

Author Comment

by:c7c4c7
ID: 39742232
Any update on this or is it not possible to do
it?
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 39742631
It is, Christmas got in the way a bit is all. Got back home a few hours ago, I'll put it together tomorrow if my daughter permits :)

CHris
0
Free Trending Threat Insights Every Day

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 

Author Comment

by:c7c4c7
ID: 39742813
I figured that might be the reason, just cheking

Thanks
0
 
LVL 70

Accepted Solution

by:
Chris Dent earned 500 total points
ID: 39752184
Many apologies for the very late reply. I hope you had a good new year.

Part 1: Adding the img tag into the HTML file

I'm using a fixed ContentID source here, the image must be attached to the mail. We cannot literally embed it into the HTML file itself.
<#
.SYNOPSIS
Generates an HTML-based system report for a computer.
Results are placed in a separate HTML file;

This version implements Style Sheets and WMI
The path of the folder where the files should be written.

#>

$computerName = get-content env:computername
$date = Get-Date -format d


$filepath = "c:\bat\logs\events.html"
$path = "C:\bat\config.txt"
$CobianDir = "C:\Program Files (x86)\Cobian Backup 11\Logs"
$goodCompletion = "Backup done for the task"

$FilezillaDir = "C:\Program Files (x86)\FileZilla Server\Logs"
$filezillaCompletion = "221 Goodbye"


$computers = $env:computername
$archive = (gc $path)

$style = "<style>$(get-content C:\Powershell\CSS\style.css)</style>"


#Computer Name
	$wmi = Get-WmiObject -Class Win32_OperatingSystem -Computer $computername
	$bootime = $wmi.ConvertToDateTime($wmi.LastBootUpTime) | select Date |ConvertTo-HTML -Fragment -PreContent "<h2>LastBoot Time</h2>" |Out-String

#unplanned Outage
	$unplanned = get-eventlog -logname system -EntryType error -After ((Get-Date).Date.AddDays(-1))  | ?{$_.eventid -eq "6008" } | ConvertTo-HTML -Fragment -PreContent "<h2>Unexpected Shutdown</h2>" | Out-String

#Ghost	
	$service =  "Norton Ghost"

	$ghost = get-eventlog -logname application -EntryType information -After ((Get-Date).Date.AddDays(-1))  | ?{$_.eventid -eq "100" -and $_.source -eq "Norton Ghost" } | ConvertTo-HTML -Fragment -PreContent "<h2>Norton Ghost</h2>" | Out-String

#Cobian		
	$service =  "CobianBackup"
	$cobian = get-eventlog -logname application -EntryType information -After ((Get-Date).Date.AddDays(-1))  | ?{$_.eventid -eq "100" -and $_.source -eq "Cobian Backup" } | ConvertTo-HTML -Fragment -PreContent "<h2>Cobian Backup</h2>" | Out-String
	
	If (Test-Path $CobianDir){
		$latest = Get-ChildItem -Path $CobianDir| Sort-Object LastAccessTime -Descending | Select-Object -First 1
		$stuff = get-content $CobianDir"\"$latest | select-string -pattern $goodCompletion -casesensitive
		$cobianlog = $stuff | ConvertTo-HTML -Fragment -PreContent "<h2>Cobian Log</h2>" | Out-String
		}
	$cobianlog = $stuff | ConvertTo-HTML -Fragment -PreContent "<h2>Cobian Log</h2>" | Out-String
	
#Filezilla
	Remove-Variable stuff
	If (Test-Path $FilezillaDir){
		$latest = Get-ChildItem -Path $FilezillaDir| Sort-Object LastAccessTime -Descending | Select-Object -First 1
		$stuff = get-content $FilezillaDir"\"$latest | select-string -pattern $filezillaCompletion -casesensitive
		$Filezillalog = $stuff |Group-Object -property source -noelement | select Line |ConvertTo-HTML -Fragment -PreContent "<h2>Filezilla Log</h2>" | Out-String
		}
	$Filezillalog  = $stuff |Group-Object -property source -noelement | select Line |ConvertTo-HTML -Fragment -PreContent "<h2>Filezilla Log</h2>" | Out-String
	

#Event Logs
#System Error
	$events = Get-Eventlog -logname system -EntryType Error -After ((Get-Date).Date.AddDays(-1))
	$system_errors = $events | Group-Object -property source -noelement | Sort-Object -property count -descending | select Count,Name | ConvertTo-HTML -Fragment -PreContent "<h2>System Errors</h2>"| Out-String


#Application Error
	$events = Get-Eventlog -logname application -EntryType Error -After ((Get-Date).Date.AddDays(-1))
	$application_errors = $events| Group-Object -property source -noelement | Sort-Object -property count -descending | select Count,Name | ConvertTo-HTML -Fragment -PreContent "<h2>Application Errors</h2>"| Out-String


#System Warning
	$events = Get-Eventlog -logname system -EntryType warning -After ((Get-Date).Date.AddDays(-1))
	$system_warning = $events| Group-Object -property source -noelement | Sort-Object -property count -descending | select Count,Name | ConvertTo-HTML -Fragment -PreContent "<h2>System Warnings</h2>"| Out-String


#Application Warning
	$events = Get-Eventlog -logname application -EntryType warning -After ((Get-Date).Date.AddDays(-1))
	$application_warning = $events| Group-Object -property source -noelement | Sort-Object -property count -descending | select Count,Name | ConvertTo-HTML -Fragment -PreContent "<h2>Application Warnings</h2>"| Out-String


#Memory Usage
	$memory = (get-content "c:\bat\logs\Results.txt")

	$memoryList = ($memory | Select @{N="Memory Usage";E={$_.Trim()}} | ConvertTo-Html -Fragment -PreContent "<h2>Memory Usage</h2>" ) | Out-String	
	#$stuff = Get-Content "C:\Bat\logs\MemoryUseage.png"	
	
  #
  # The position of the graph within the HTML can be changed, this simply appends the
  # img fragment after the $memoryList generated above.
  #
  # The file must be attached to the e-mail, and the content ID of the file must 
  # be set to MemoryGraph for this to display.
 
  $memoryGraph = "<IMG SRC='cid:MemoryGraph' ALT='$computer Chart'>"	
  $memoryList = $memoryList + $memoryGraph
	
#Drive Info
	$driveinfo = Get-WMIobject win32_LogicalDisk -computername $computers -filter "DriveType=3" | 
		Select-Object SystemName,DeviceID,@{Name="Size(GB)";Expression={"{0:N1}" -f($_.size/1gb)}},`
		@{Name="FreeSpace(GB)";Expression={"{0:N1}" -f($_.freespace/1gb)}},`
		@{Name="% FreeSpace(GB)";Expression={"{0:N2}%" -f(($_.freespace/$_.size)*100)}}| ConvertTo-HTML -Fragment -PreContent "<h2>Drive information</h2>"| Out-String

#Collect all of the parameters from above items
if (3.0 -eq $PSVersionTable.PSVersion ) {
	$params = @{'Head'="<title>Daily Report for $computer - $date</title>$style";
		'PreContent'="<h1>System Event Report for $computerName  - $date</h1>";
		'PostContent'=$bootime, $unplanned, $ghost, $cobian, $cobianlog, $Filezillalog , $system_errors, $application_errors,$system_warning, $application_warning, $memorylist, $driveinfo}
	} else
	{
	$params = @{'Head'="<title>Daily Report for $computer - $date</title>$style";
		'PreContent'="<h1>System Event Report for $computerName  - $date</h1>";
		'PostContent'=$bootime, $unplanned, $ghost, $cobian, $cobianlog, $Filezillalog , $system_errors, $application_errors,$system_warning, $application_warning, $memorylist, $driveinfo}
	}

#Convert it all to HTML
#put it in the directory
	ConvertTo-HTML @params | Out-File -FilePath $filepath
	

#Clear the Memory file 1st of each month
#Archive the old file
	$firstDayOfMonth = Get-Date ((((Get-Date $date).Month).ToString() + "/1/" + ((Get-Date $date).Year).ToString() + " 00:00:00")) 
	$lastDayOfMonth = ((Get-Date ((((Get-Date $firstDayOfMonth).AddMonths(1)).Month).ToString() + "/1/" + (((Get-Date $firstDayOfMonth).AddMonths(1)).Year).ToString()))) - (New-TimeSpan -seconds 1)
	if ($date -eq $lastDayofMonth.ToShortDateString()) {
		$month = get-date -format MMMM
			if (!(Test-Path -path $archive))
			 {
			 New-Item $archive -type directory
			 }
		Copy-Item C:\bat\logs\Results.txt $archive\$month.txt
		clear-content C:\bat\logs\Results.txt
		}

Open in new window

Part 2: Generating an HTML mail with an attachment we can reference

Now we create an instance of the attachment, then use .NET classes to send the mail message. Send-MailMessage isn't quite flexible enough for this.

$SmtpServer = "Mailserver"
$To = "me@domain.example"
$From = "me@domain.example"
$Subject = "The subject"
# The HTML content
$BodyPath = "c:\bat\logs\events.html"
$Body = Get-Content $BodyPath | Out-String
# The real path to the attachment
$AttachmentPath = "C:\Bat\logs\MemoryUseage.png"

$SmtpClient = New-Object System.Net.Mail.SmtpClient($SmtpServer)

# Argument order for constructor is From, To, Subject, Body
$MailMessage = New-object System.Net.Mail.MailMessage($From, $To, $Subject, $Body)

# Sort out the attachemnt
$Attachment = New-Object System.Net.Mail.Attachment($AttachmentPath)
$Attachment.ContentID = "MemoryGraph"

# And add it onto the mail
$MailMessage.Attachments.Add($Attachment)

# Send the message
$SmtpClient.Send($MailMessage)

# Unlock the file (just a file-open lock)
$Attachment.Dispose()

Open in new window

Please yell if it doesn't work, I haven't had an opportunity to fully test this.

Chris
0
 

Author Comment

by:c7c4c7
ID: 39752435
Don't really understand how this works.  How does it know where to find the PNG?  Will it only work from an email message or will it work if the html and the png are in the same directory?

Thanks
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 39752615
The snippets above will only work for an e-mail message. The first part generates the content you need to work with the second. They cannot be split as they stand.

If the two files are in the same directory you can simply use a link as you did in the original to get the image. The trouble is it's not portable, HTML cannot embed images, it only allows you to display them. Therefore whatever images you use must be available to the person loading the HTML file.

Chris
0
 

Author Comment

by:c7c4c7
ID: 39758332
When I open the email to view the HTML attachment it has a broken link where the picture should be.  It's probably something obvious but I don't see it
events.html
MemoryGraph.png
sendemail.txt
createReport.txt
0
 
LVL 39

Expert Comment

by:footech
ID: 39758525
When I saw this question I was curious about the answer as I really haven't yet faced the situation where I needed to generate a HTML email with an embedded image.

No points needed for me as Chris has really done all the work.  The only change I needed to make was to add the following after line 14 of the email generation code he posted for it to work.
$MailMessage.IsBodyHtml = $true
The body of the mail message is the events.html report created from the other bit of code.  I'm doubtful it would work with the HTML file attached (instead of being the body) as you did in your last post.
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 39758693
Thanks footech, good catch :)

Events.html must be the body of the message, you cannot do it like this otherwise.

It certainly won't work if it's an HTML file attachment. The browser will load the file from a temporary directory (ultimately), and would therefore need the image file available somewhere it could reach. In that instance the image would have to be available on a web server or a UNC path to display.

If it's important to really embed the image, and to have the report shipped as an attachment, you need another file format. There's a possibility we could generate a word-file based on the HTML file (if Word is installed on the system generating the report).

Perhaps using something something like this:

http://blogs.technet.com/b/bshukla/archive/2010/07/29/how-to-convert-a-word-document-to-other-formats-using-powershell.aspx

Chris
0
 

Author Comment

by:c7c4c7
ID: 39760635
So if the report was sent as the email body rather than an attachment an the graph WAS sent as an attachment it would work then?

I cannot guarantee Word will always be available on the machines
0
 
LVL 70

Expert Comment

by:Chris Dent
ID: 39761492
Yes, it should (with the modification footech provided). In that instance the image will be available in a location relative to the HTML, and as long as I matched everything up properly above, it will load.

Chris
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

How to sign a powershell script so you can prevent tampering, and only allow users to run authorised Powershell scripts
I thought I'd write this up for anyone who has a request to create an anonymous whistle-blower-type submission form created using SharePoint 2010 (this would probably work the same for 2013). It's not 100% fool-proof but it's as close as you can get…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now