Create HTML email report using PowerShell

HTML report

Create HTML report using PowerShell. Some time ago I added a post about creating your own report. This time I wanted to show you how to create a basic system performance report and send it to your mailbox.

HTML Report

Below you can find PowerShell script for checking the following system details using Get-WMIObject remotely:

  • BootUpTime
  • UpTime
  • C: Free space %
  • PhysicalRAM
  • Memory %
  • CPU %

You need to have ActiveDirectory module as the script is getting all Domain Controllers in your domain first. Get-ADDomainController gets one or more Active Directory domain controllers based on discoverable services criteria, search parameters or by providing a domain controller identifier, such as the NetBIOS name

For each server it will get performance details remotely using Invoke-Command:

$DCs = (Get-ADDomainController -Filter *).name | Sort-Object    
Invoke-Command -cn $DCs {
	             
	                # Define object with properties
	                $Object = @{} | select "BootUpTime", 
                                           "UpTime", 
                                           "C: Free space %", 
                                           "PhysicalRAM", 
                                           "Memory %", 
                                           "CPU %"
	            
	                # Get OS details using WMI query
	                $System = Get-WmiObject win32_operatingsystem | Select-Object LastBootUpTime,LocalDateTime,TotalVisibleMemorySize,FreePhysicalMemory
	                 
	                # Get bootup time and local date time  
	                $LastBootUpTime = [Management.ManagementDateTimeConverter]::ToDateTime(($System).LastBootUpTime)
	                $LocalDateTime  = [Management.ManagementDateTimeConverter]::ToDateTime(($System).LocalDateTime)
	 
	                # Calculate uptime - this is automatically a timespan
	                $up = $LocalDateTime - $LastBootUpTime
	                $uptime = "$($up.Days) days, $($up.Hours)h, $($up.Minutes)mins"
	 
	                $Object.BootUpTime        = $LastBootUpTime
	                $Object.UpTime            = $uptime
	                $Object.'C: Free space %' = (Get-WmiObject -Class Win32_Volume -Filter "DriveLetter = 'C:'" | Select-object @{Name = "C PercentFree"; Expression = {“{0:N2}” -f  (($_.FreeSpace / $_.Capacity)*100) } }).'C PercentFree' 
	                $Object."PhysicalRAM"     = (Get-WMIObject -class Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | % {[Math]::Round(($_.sum / 1GB),2)})
	                $Object."Memory %"        = ($System | Select-Object @{Name = "MemoryUsage"; Expression = { “{0:N2}” -f ((($_.TotalVisibleMemorySize - $_.FreePhysicalMemory)*100)/ $_.TotalVisibleMemorySize)}}).MemoryUsage
	                $Object."CPU %"           = (Get-WmiObject Win32_processor |  Measure-Object -property LoadPercentage -Average | Select Average).Average  

                    # Return object  
	                $Object
	             
} | Select-Object @{n='ServerName';e={$_.pscomputername}},"BootUpTime", "UpTime", "C: Free space %", "PhysicalRAM", "Memory %", "CPU %"

Next, we have to convert this to HTML using a simple function:

# Function: Array > Html  
Function Create-HTMLTable{ 
    param([array]$Array)      
    $arrHTML = $Array | ConvertTo-Html
    $arrHTML[-1] = $arrHTML[-1].ToString().Replace('</body></html>'," ")    
    Return $arrHTML[5..2000]
}

Let’s add HMTL style to our script:

$Style = @"
<style>
  body {
    font-family: "Arial";
    font-size: 8pt;
    color: #4C607B;
    }
  th, td { 
    border: 1px solid #e57300;
    border-collapse: collapse;
    padding: 5px;
    }
  th {
    font-size: 1.2em;
    text-align: left;
    background-color: #003366;
    color: #ffffff;
    }
  td {
    color: #000000;
    }
  .even { background-color: #ffffff; }
  .odd { background-color: #bfbfbf; }
</style>
"@

Remember to provide Email address and SMTP:

#Email
$Email = (Get-ADUser -Identity $ENV:Username -Properties mail).mail 

#Email Params
$Parameters = @{
    From        = "reports@powershellbros.com"
    To          = $Email
    Subject     = "[Report] Performance $(Get-Date -Format "yyyy-MM-dd")"
    Body        = $Output
    BodyAsHTML  = $True
    CC          = $Email
    Port        = '25'
    Priority    = "Normal"
    SmtpServer  = "SMTP.PowerShellBros.com"
}
 
#Sending email
Send-MailMessage @Parameters

Below you can find script for creating HTML formatted performance report:

### PARAMS #################################################################################################################################
# Import AD module
Import-Module ActiveDirectory
 	
# Function: Array > Html  
Function Create-HTMLTable{ 
    param([array]$Array)      
    $arrHTML = $Array | ConvertTo-Html
    $arrHTML[-1] = $arrHTML[-1].ToString().Replace('</body></html>'," ")    
    Return $arrHTML[5..2000]
}
 
# Define empty array
$Report = @()
	 
# Get all domain controllers
$DCs = (Get-ADDomainController -Filter *).name | Sort-Object
	    

### PERFORMANCE ############################################################################################################################
Try{
    $Report = Invoke-Command -cn $DCs {
	             
	                # Define object with properties
	                $Object = @{} | select "BootUpTime", 
                                           "UpTime", 
                                           "C: Free space %", 
                                           "PhysicalRAM", 
                                           "Memory %", 
                                           "CPU %"
	            
	                # Get OS details using WMI query
	                $System = Get-WmiObject win32_operatingsystem | Select-Object LastBootUpTime,LocalDateTime,TotalVisibleMemorySize,FreePhysicalMemory
	                 
	                # Get bootup time and local date time  
	                $LastBootUpTime = [Management.ManagementDateTimeConverter]::ToDateTime(($System).LastBootUpTime)
	                $LocalDateTime  = [Management.ManagementDateTimeConverter]::ToDateTime(($System).LocalDateTime)
	 
	                # Calculate uptime - this is automatically a timespan
	                $up = $LocalDateTime - $LastBootUpTime
	                $uptime = "$($up.Days) days, $($up.Hours)h, $($up.Minutes)mins"
	 
	                $Object.BootUpTime        = $LastBootUpTime
	                $Object.UpTime            = $uptime
	                $Object.'C: Free space %' = (Get-WmiObject -Class Win32_Volume -Filter "DriveLetter = 'C:'" | Select-object @{Name = "C PercentFree"; Expression = {“{0:N2}” -f  (($_.FreeSpace / $_.Capacity)*100) } }).'C PercentFree' 
	                $Object."PhysicalRAM"     = (Get-WMIObject -class Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | % {[Math]::Round(($_.sum / 1GB),2)})
	                $Object."Memory %"        = ($System | Select-Object @{Name = "MemoryUsage"; Expression = { “{0:N2}” -f ((($_.TotalVisibleMemorySize - $_.FreePhysicalMemory)*100)/ $_.TotalVisibleMemorySize)}}).MemoryUsage
	                $Object."CPU %"           = (Get-WmiObject Win32_processor |  Measure-Object -property LoadPercentage -Average | Select Average).Average  

                    # Return object  
	                $Object
	             
    }  -ErrorAction Stop | Select-Object @{n='ServerName';e={$_.pscomputername}},"BootUpTime", "UpTime", "C: Free space %", "PhysicalRAM", "Memory %", "CPU %"
}
Catch [System.Exception]{
    Write-host "Error" -backgroundcolor red -foregroundcolor yellow
    $_.Exception.Message
}
	 
#Display results
$Report | Format-Table -AutoSize -Wrap 


### HTML REPORT ############################################################################################################################
# Creating head style
$Style = @"
	 
	<style>
	  body {
	    font-family: "Arial";
	    font-size: 8pt;
	    color: #4C607B;
	    }
	  th, td { 
	    border: 1px solid #e57300;
	    border-collapse: collapse;
	    padding: 5px;
	    }
	  th {
	    font-size: 1.2em;
	    text-align: left;
	    background-color: #003366;
	    color: #ffffff;
	    }
	  td {
	    color: #000000;
	    }
	  .even { background-color: #ffffff; }
	  .odd { background-color: #bfbfbf; }
	</style>
	 
"@
# Creating head style and header title
$output = $null
$output = @()
$output += '<html><head></head><body>'
$output +=

#Import hmtl style file
$Style

$output += "<h3 style='color: #0B2161'>Performance report</h3>"
$output += '<strong><font color="red">WARNING: </font></strong>'
$output += "Please review attached report.</br>" 
$output += '</br>'
$output += '<hr>' 
$output += '<p>'
$output += "<h4>Report for $(($DCs | Measure-Object).count) domain controllers:</h4>"
$output += '<p>'
$output += Create-HTMLTable $Report
$output += '</p>'
$output += '</body></html>'
$output =  $output | Out-String


### SENDING EMAIL ##########################################################################################################################
#Email
$Email = (Get-ADUser -Identity $ENV:Username -Properties mail).mail 

#Email Params
$Parameters = @{
    From        = "reports@powershellbros.com"
    To          = $Email
    Subject     = "[Report] Performance $(Get-Date -Format "yyyy-MM-dd")"
    Body        = $Output
    BodyAsHTML  = $True
    CC          = $Email
    Port        = '25'
    Priority    = "Normal"
    SmtpServer  = "SMTP.PowerShellBros.com"
}

#Sending email
Send-MailMessage @Parameters 

I hope this was informative for you 🙂 See you in the next articles.

3 thoughts on “Create HTML email report using PowerShell

  1. The script is very useful for me Thank you very much.

    Please can you help me as I want to add ServiceInfo and PatchInfo in the report.

    SevicesInfo is any auto services in the stopped state and PatchInfo is Last 2 patched information, below is the ps command..

    $SevicesInfo= Get-WmiObject Win32_Service | Where-Object { $_.StartMode -eq ‘Auto’ -and $_.State -ne ‘Running’ }

    $PatchInfo= = Get-WmiObject Win32_QuickFixEngineering -computer $server | SELECT HotFixID,Description,@{Name=”InstalledOn”;Expression={$_.InstalledOn -as [datetime]}},InstalledBy |Sort-Object -Property InstalledOn | Select-Object -Property InstalledOn,HotFixID,Description,InstalledBy -Last 2 | out-string;

    1. I managed to get it finally, but still needs cosmetic touch..

      ort = Invoke-Command -cn $DCs {

      # Define object with properties
      $Object = @{} | select “BootUpTime”,
      “UpTime”,
      “C: Free space %”,
      “PhysicalRAM”,
      “Memory %”,
      “CPU %”,
      “AutoServicesStopped”,
      “Last2PatchInfo”

      # Get OS details using WMI query
      $System = Get-WmiObject win32_operatingsystem | Select-Object LastBootUpTime,LocalDateTime,TotalVisibleMemorySize,FreePhysicalMemory

      # Get bootup time and local date time
      $LastBootUpTime = [Management.ManagementDateTimeConverter]::ToDateTime(($System).LastBootUpTime)
      $LocalDateTime = [Management.ManagementDateTimeConverter]::ToDateTime(($System).LocalDateTime)

      # Calculate uptime – this is automatically a timespan
      $up = $LocalDateTime – $LastBootUpTime
      $uptime = “$($up.Days) days, $($up.Hours)h, $($up.Minutes)mins”

      # Check Services on each Server
      $AutoServices = Get-WmiObject Win32_Service | Where-Object { $_.StartMode -eq ‘Auto’ -and $_.State -ne ‘Running’ } | select DisplayName

      # Check Patching info on each Server
      $PatchingInfo = Get-WmiObject Win32_QuickFixEngineering | SELECT HotFixID,Description,@{Name=”InstalledOn”;Expression={$_.InstalledOn -as [datetime]}},InstalledBy |Sort-Object -Property InstalledOn | Select-Object -Property InstalledOn,HotFixID -Last 2 | out-string;

      $Object.BootUpTime = $LastBootUpTime
      $Object.UpTime = $uptime
      $Object.’C: Free space %’ = (Get-WmiObject -Class Win32_Volume -Filter “DriveLetter = ‘C:'” | Select-object @{Name = “C PercentFree”; Expression = {“{0:N2}” -f (($_.FreeSpace / $_.Capacity)*100) } }).’C PercentFree’
      $Object.”PhysicalRAM” = (Get-WMIObject -class Win32_PhysicalMemory | Measure-Object -Property capacity -Sum | % {[Math]::Round(($_.sum / 1GB),2)})
      $Object.”Memory %” = ($System | Select-Object @{Name = “MemoryUsage”; Expression = { “{0:N2}” -f ((($_.TotalVisibleMemorySize – $_.FreePhysicalMemory)*100)/ $_.TotalVisibleMemorySize)}}).MemoryUsage
      $Object.”CPU %” = (Get-WmiObject Win32_processor | Measure-Object -property LoadPercentage -Average | Select Average).Average
      $Object.”AutoServicesStopped” = $AutoServices.DisplayName
      $Object.”Last2PatchInfo” = $PatchingInfo

      # Return object
      $Object

      } -ErrorAction Stop | Select-Object @{n=’ServerName’;e={$_.pscomputername}},”BootUpTime”, “UpTime”, “C: Free space %”, “PhysicalRAM”, “Memory %”, “CPU %”, “AutoServicesStopped”, “Last2PatchInfo”
      }
      Catch [System.Exception]{
      Write-host “Error” -backgroundcolor red -foregroundcolor yellow
      $_.Exception.Message
      }

      #Display results
      $Report | Format-Table -AutoSize -Wrap

      ### HTML REPORT ############################################################################################################################
      # Creating head style
      $Style = @”

      body {
      font-family: “Arial”;
      font-size: 8pt;
      color: #4C607B;
      }
      th, td {
      border: 1px solid #e57300;
      border-collapse: collapse;
      padding: 5px;
      }
      th {
      font-size: 1.2em;
      text-align: left;
      background-color: #003366;
      color: #ffffff;
      }
      td {
      color: #000000;
      }
      .even { background-color: #ffffff; }
      .odd { background-color: #bfbfbf; }

      “@
      # Creating head style and header title
      $output = $null
      $output = @()
      $output += ”
      $output +=

      #Import hmtl style file
      $Style

      $output += “Performance report”
      $output += ‘WARNING:
      $output += “Please review attached report.”
      $output += ”
      $output += ”
      $output += ”
      $output += “Report for $(($DCs | Measure-Object).count) domain controllers:”
      $output += ”
      $output += Create-HTMLTable $Report
      $output += ”
      $output += ”
      $output = $output | Out-String
      $output | Out-File “C:\temp\hcnew.html” -Force

  2. Where { $_.LastBootUpTime -lt $UptimeThresholdDate } not working with Invoke-command. Any suggestion.

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.