Windows PowerShell script that creates a system status HTML report with information gathered from WMI.

#requires -version 2.0

 Script: MorningReport.ps1
 Version: 1.0
 Author: Jeffery Hicks
 Date: 1/9/2012

  - Article:
  - Script:
  - Example Report:

Create System Report
Create a system status report with information gathered from WMI. The
default output are pipelined objects. But you can also use -TEXT to write
a formatted text report, suitable for sending to a file or printer, or
-HTML to create HTML code. You will need to pipe the results to Out-File
if you want to save it.
.Parameter Computername
The name of the computer to query. The default is the localhost.
.Parameter ReportTitle
The title for your report. This parameter has an alias of 'Title'.
.Parameter Hours
The number of hours to search for errors and warnings.
The default is 24.
.Parameter HTML
Create HTML report. You must pipe to Out-File to save the results.
.Parameter Text
Create a formatted text report
PS C:\Scripts\> .\MorningReport | Export-Clixml ("c:\work\{0:yyyy-MM-dd}_{1}.xml" -f (get-date),$env:computername)
Preparing morning report for SERENITY
...Operating System
...Computer System
...Logical Disks
...Network Adapters
...System Event Log Error/Warning since 01/09/2012 09:47:26
...Application Event Log Error/Warning since 01/09/2012 09:47:26

Run a morning report and export it to an XML file with a date stamped file name.
PS C:\Scripts\> .\MorningReport Quark -Text | Out-file c:\work\quark-report.txt
Run a morning report for a remote computer and save the results to an text file.
PS C:\Scripts\> .\MorningReport -html -hours 30 | Out-file MyReport.htm
Run a morning report for the local computer and get last 30 hours of event log information. Save as an HTML report.
Custom object, text or HTML code


    [Parameter(Position=0,ValueFromPipeline=$True)] [ValidateNotNullOrEmpty()] [string]$Computername=$env:computername,
    [ValidateNotNullOrEmpty()] [alias("title")] [string]$ReportTitle="System Report",
    [ValidateScript({$_ -ge 1})] [int]$Hours=24,
    [Parameter(ParameterSetName="HTML")] [switch]$HTML,
    [Parameter(ParameterSetName="TEXT")] [switch]$Text

#script internal version number used in output

define some HTML style
here's a source for HTML color codes

the code must be left justified
$head = @"
<title>$ReportTitle for $computername</title>
<style type="text/css">
body {
    font-family: "Helvetica Neue", Helvetica, "Segoe UI", Arial, freesans, sans-serif;
    font-size: 14px;
    line-height: 1.4;
    color: #333;
td, th {
    border:1px solid #EEE;
th {
table, tr, td, th {
    padding: 2px;
    margin: 0px;
table {
    margin-left: 50px;
    table-layout: fixed;
    min-width: 920px !important;

If ($computername -eq $env:computername) {
    #local computer so no ping test is necessary
elseIf (($computername -ne $env:computername) -AND (Test-Connection -ComputerName $computername -quiet -Count 2)) {
    #not local computer and it can be pinged so proceed

If ($OK) {
    Try {
        $os=Get-WmiObject Win32_operatingSystem -ComputerName $computername -ErrorAction Stop
        #set a variable to indicate WMI can be reached
    Catch {
        Write-Warning "WMI failed to connect to $($computername.ToUpper())"

    if ($wmi) {
        Write-Host "Preparing morning report for $($os.CSname)" -ForegroundColor Cyan

        #OS Summary
        Write-Host "...Operating System" -ForegroundColor Cyan
        $osdata=$os | Select @{Name="Computername";Expression={$_.CSName}},
        @{Name="Uptime";Expression={(Get-Date) - ($_.ConvertToDateTime($_.LastBootupTime))}}

        #Computer system
        Write-Host "...Computer System" -ForegroundColor Cyan
        $cs=Get-WmiObject -Class Win32_Computersystem -ComputerName $computername
        $csdata=$cs | Select Status,Manufacturer,Model,SystemType,Number*

        Write-Host "...Services" -ForegroundColor Cyan
        #get services via WMI and group into a hash table
        $wmiservices=Get-WmiObject -class Win32_Service -ComputerName $computername
        $services=$wmiservices | Group State -AsHashTable

        #get services set to auto start that are not running
        $failedAutoStart=$wmiservices | Where { ($_.startmode -eq "Auto") -AND ($_.state -ne "Running")}

        #Disk Utilization
        Write-Host "...Logical Disks" -ForegroundColor Cyan
        $disks=Get-WmiObject -Class Win32_logicaldisk -Filter "Drivetype=3" -ComputerName $computername
        $diskData=$disks | Select DeviceID,
        @{Name="SizeGB";Expression={$_.size/1GB -as [int]}},
        @{Name="FreeGB";Expression={"{0:N2}" -f ($_.Freespace/1GB)}},
        @{Name="PercentFree";Expression={"{0:P2}"  -f ($_.Freespace/$_.Size)}}

        Write-Host "...Network Adapters" -ForegroundColor Cyan
        #get NICS that have a MAC address only
        $nics=Get-WmiObject -Class Win32_NetworkAdapter -filter "MACAddress Like '%'" -ComputerName $Computername
        $nicdata=$nics | Foreach {
         #get related configuation information
         $config=$_.GetRelated() | where {$_.__CLASS -eq "Win32_NetworkadapterConfiguration"}
         #add to temporary hash
         #convert lease information if found
         if ($config.DHCPEnabled -AND $config.DHCPLeaseObtained) {

         New-Object -TypeName PSObject -Property $tempHash


        #Event log errors and warnings in the last $Hours hours
        #System Log
        Write-Host "...System Event Log Error/Warning since $last" -ForegroundColor Cyan
        $syslog=Get-EventLog -LogName System -ComputerName $computername -EntryType Error,Warning -After $last
        $syslogdata=$syslog | Select TimeGenerated,EventID,Source,Message

        #Application Log
        Write-Host "...Application Event Log Error/Warning since $last" -ForegroundColor Cyan
        $applog=Get-EventLog -LogName Application -ComputerName $computername -EntryType Error,Warning -After $last
        $applogdata=$applog | Select TimeGenerated,EventID,Source,Message

    } #if wmi is ok

    #write results depending on parameter set
    # $footer="Report v{3} run {0} by {1}\{2}" -f (Get-Date),$env:USERDOMAIN,$env:USERNAME,$reportVersion
    $footer="Report run {0} by {1}\{2}" -f (Get-Date),$env:USERDOMAIN,$env:USERNAME

    if ($HTML) {
        #prepare HTML code
        $fragments+="<h1>$ReportTitle - $computername</h1>"

#insert navigation bookmarks
<div style="margin-top: 10px; margin-bottom: 10px;">
<a href='#Services'>Services</a>
<a href='#NoAutoStart'>Failed Auto Start</a>
<a href='#Disks'>Disks</a>
<a href='#Network'>Network</a>
<a href='#SysLog'>System Log</a>
<a href='#AppLog'>Application Log</a>
        $fragments+="<br clear='all'>"

        #add a link to the document top
        $nav+="`n<a href='#' target='_top'>Top</a>"

        $fragments+="<h2>System Summary</h2>"
        $fragments+=$osdata | ConvertTo-Html -as List -Fragment
        $fragments+=$csdata | ConvertTo-Html -as List -Fragment
        $fragments+=ConvertTo-Html -Fragment -PreContent "<h2><a name='Services'>Services</a></h2>"
        $services.keys | foreach {
         $fragments+= ConvertTo-Html -Fragment -PreContent "<h3>$_</h3>"
         $fragments+=$services.$_ | Select Name,Displayname,StartMode| ConvertTo-HTML -Fragment
         #insert navigation link after each section

        $fragments+=$failedAutoStart | Select Name,Displayname,StartMode,State |
         ConvertTo-Html -Fragment -PreContent "<h3><a name='NoAutoStart'>Failed Auto Start</a></h3>"

        $fragments+=$diskdata | ConvertTo-HTML -Fragment -PreContent "<h2><a name='Disks'>Disk Utilization</a></h2>"

        #convert nested object array properties to strings
        $fragments+=$nicdata | Select Name,DeviceID,DHCP*,AdapterType,MACAddress,
         @{Name="IPAddress";Expression={$_.IPAddress | Out-String}},
         @{Name="IPSubnet";Expression={$_.IPSubnet | Out-String}},
         @{Name="IPGateway";Expression={$_.DefaultGateway | Out-String}}  |
          ConvertTo-HTML -Fragment -PreContent "<h2><a name='Network'>Network Adapters</a></h2>"

        $fragments+=$syslogData | ConvertTo-HTML -Fragment -PreContent "<h2><a name='SysLog'>System Event Log Summary</a></h2>"

        $fragments+=$applogData | ConvertTo-HTML -Fragment -PreContent "<h2><a name='AppLog'>Application Event Log Summary</a></h2>"

        Write $fragments | clip
        ConvertTo-Html -Head $head -Title $ReportTitle -PreContent ($fragments | out-String) -PostContent "<br><i>$footer</i>"
    elseif ($TEXT) {
        #prepare formatted text
        "System Summary"
        $osdata | Out-String
        $csdata | format-List | Out-String
        Write "Services"
        $services.keys | foreach {
            $services.$_ | Select Name,Displayname,StartMode,State
        } | Format-List | Out-String
        Write "Failed Autostart Services"
        $failedAutoStart | Select Name,Displayname,StartMode,State
        Write "Disk Utilization"
        $diskdata | Format-table -AutoSize | Out-String
        Write "Network Adapters"
        $nicdata | Format-List | Out-String
        Write "System Event Log Summary"
        $syslogdata | Format-List | Out-String
        Write "Application Event Log Summary"
        $applogdata | Format-List | Out-String
        Write $Footer
    else {
        #Write data to the pipeline as part of a custom object
        New-Object -TypeName PSObject -Property @{
        Services=$services.keys | foreach {$services.$_ | Select Name,Displayname,StartMode,State}
        FailedAutoStart=$failedAutoStart | Select Name,Displayname,StartMode,State
} #if OK
else {
    #can't ping computer so fail
    Write-Warning "Failed to ping $computername"
#end of script