?
Solved

How to include a picture in an HTML Document using powershell

Posted on 2013-12-21
18
Medium Priority
?
3,704 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 9
  • 8
18 Comments
 
LVL 71

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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 71

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 71

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 71

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
 

Author Comment

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

Thanks
0
 
LVL 71

Accepted Solution

by:
Chris Dent earned 2000 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 71

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 40

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 71

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 71

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

Does Powershell have you tied up in knots?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article will help you understand what HashTables are and how to use them in PowerShell.
In previous parts of this Nano Server deployment series, we learned how to create, deploy and configure Nano Server as a Hyper-V host. In this part, we will look for a clustering option. We will create a Hyper-V cluster of 3 Nano Server host nodes w…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an antispam), the admini…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.

801 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