• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 4721
  • Last Modified:

How to include a picture in an HTML Document using powershell

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?
  • 9
  • 8
1 Solution
Chris DentPowerShell DeveloperCommented:
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.

c7c4c7Author Commented:
I want the picture imbeded in the html.  The picture resides on a machine without a web server.
c7c4c7Author Commented:
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?
Protect Your Employees from Wi-Fi Threats

As Wi-Fi growth and popularity continues to climb, not everyone understands the risks that come with connecting to public Wi-Fi or even offering Wi-Fi to employees, visitors and guests. Download the resource kit to make sure your safe wherever business takes you!

Chris DentPowerShell DeveloperCommented:

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:


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

c7c4c7Author Commented:
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?

Chris DentPowerShell DeveloperCommented:
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.

c7c4c7Author Commented:
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.
c7c4c7Author Commented:
Any update on this or is it not possible to do
Chris DentPowerShell DeveloperCommented:
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 :)

c7c4c7Author Commented:
I figured that might be the reason, just cheking

Chris DentPowerShell DeveloperCommented:
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.
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

	$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

	$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
	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

# Send the message

# Unlock the file (just a file-open lock)

Open in new window

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

c7c4c7Author Commented:
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?

Chris DentPowerShell DeveloperCommented:
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.

c7c4c7Author Commented:
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
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.
Chris DentPowerShell DeveloperCommented:
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:


c7c4c7Author Commented:
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
Chris DentPowerShell DeveloperCommented:
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.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

Join & Write a Comment

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

  • 9
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now