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.
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;
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
Where { $_.LastBootUpTime -lt $UptimeThresholdDate } not working with Invoke-command. Any suggestion.