#requires -version 2.0
<#
-----------------------------------------------------------------------------
Script: MorningReport.ps1
Version: 1.1.6
Author: Jeffery Hicks
http://jdhitsolutions.com/blog
http://twitter.com/JeffHicks
http://www.ScriptingGeek.com
Date: 2/13/2012
Keywords:
Comments:
Prepare a morning system status report
"Those who forget to script are doomed to repeat their work."
****************************************************************
* DO NOT USE IN A PRODUCTION ENVIRONMENT UNTIL YOU HAVE TESTED *
* THOROUGHLY IN A LAB ENVIRONMENT. USE AT YOUR OWN RISK. IF *
* YOU DO NOT UNDERSTAND WHAT THIS SCRIPT DOES OR HOW IT WORKS, *
* DO NOT USE IT OUTSIDE OF A SECURE, TEST SETTING. *
****************************************************************
-----------------------------------------------------------------------------
#>
<#
.Synopsis
Create System Report
.Description
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 Quick
Run a quick report which means no event logs queries. This
speeds up the report generation.
.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
.Example
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
...Services
...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.
.Example
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.
.Example
PS C:\Scripts\> .\MorningReport -html -hours 30 | Out-file C:\work\MyReport.htm
Run a morning report for the local computer and get last 30 hours of event log information. Save as an HTML report.
.Example
PS C:\Scripts\> get-content computers.txt | .\Morningreport -quick -html | out-file c:\work\morningreport.htm
Get the list of computers and create a single HTML report without the event log information.
.Link
http://jdhitsolutions.com/blog/2012/02/morning-report-revised
.Link
Get-WMIObject
Get-EventLog
ConvertTo-HTML
.Inputs
String
.Outputs
Custom object, text or HTML code
#>
[cmdletbinding(DefaultParameterSetName="object")]
Param(
[Parameter(Position=0,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
[ValidateNotNullOrEmpty()]
[string]$Computername=$env:computername,
[ValidateNotNullOrEmpty()]
[alias("title")]
[string]$ReportTitle="System Report",
[ValidateScript({$_ -ge 1})]
[int]$Hours=24,
[switch]$Quick,
[Parameter(ParameterSetName="HTML")]
[switch]$HTML,
[Parameter(ParameterSetName="TEXT")]
[switch]$Text
)
Begin {
#script internal version number used in output
[string]$reportVersion="1.1.6"
<#
define some HTML style
here's a source for HTML color codes
http://www.immigration-usa.com/html_colors.html
the code must be left justified
#>
$head = @"
$ReportTitle
The Morning Report
$(Get-Date -DisplayHint Date | out-string)
"@
#prepare HTML code
$fragments=@()
} #Begin
Process {
#set a default value for the ping test
$ok=$False
If ($computername -eq $env:computername) {
#local computer so no ping test is necessary
$OK=$True
}
elseIf (($computername -ne $env:computername) -AND (Test-Connection -ComputerName $computername -quiet -Count 2)) {
#not local computer and it can be pinged so proceed
$OK=$True
}
If ($OK) {
Try {
$os=Get-WmiObject Win32_operatingSystem -ComputerName $computername -ErrorAction Stop
#set a variable to indicate WMI can be reached
$wmi=$True
}
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="OS";Expression={$_.Caption}},
@{Name="ServicePack";Expression={$_.CSDVersion}},
free*memory,totalv*,NumberOfProcesses,
@{Name="LastBoot";Expression={$_.ConvertToDateTime($_.LastBootupTime)}},
@{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*
#services
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)}}
#NetworkAdapters
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 {
$tempHash=@{Name=$_.Name;DeviceID=$_.DeviceID;AdapterType=$_.AdapterType;MACAddress=$_.MACAddress}
#get related configuation information
$config=$_.GetRelated() | where {$_.__CLASS -eq "Win32_NetworkadapterConfiguration"}
#add to temporary hash
$tempHash.Add("IPAddress",$config.IPAddress)
$tempHash.Add("IPSubnet",$config.IPSubnet)
$tempHash.Add("DefaultGateway",$config.DefaultIPGateway)
$tempHash.Add("DHCP",$config.DHCPEnabled)
#convert lease information if found
if ($config.DHCPEnabled -AND $config.DHCPLeaseObtained) {
$tempHash.Add("DHCPLeaseExpires",($config.ConvertToDateTime($config.DHCPLeaseExpires)))
$tempHash.Add("DHCPLeaseObtained",($config.ConvertToDateTime($config.DHCPLeaseObtained)))
$tempHash.Add("DHCPServer",$config.DHCPServer)
}
New-Object -TypeName PSObject -Property $tempHash
}
If ($Quick) {
Write-Verbose "Skipping event log queries"
}
else {
#Event log errors and warnings in the last $Hours hours
$last=(Get-Date).AddHours(-$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
if ($HTML) {
#add each computer to a navigation menu in the header
$head+=("{0} " -f $computername.ToUpper())
$fragments+=("" -f $computername.ToUpper())
#insert navigation bookmarks
$nav=@"
{0} Services
{0} Failed Auto Start
{0} Disks
{0} Network
{0} System Log
{0} Application Log
"@ -f $Computername.ToUpper()
#add a link to the document top
$nav+="`nTop"
$fragments+=$nav
$fragments+="
"
$fragments+=$osdata | ConvertTo-Html -as List -Fragment
$fragments+=$csdata | ConvertTo-Html -as List -Fragment
$fragments+=ConvertTo-Html -Fragment -PreContent ("" -f $computername.ToUpper())
$services.keys | foreach {
$fragments+= ConvertTo-Html -Fragment -PreContent "$_
"
$fragments+=$services.$_ | Select Name,Displayname,StartMode| ConvertTo-HTML -Fragment
#insert navigation link after each section
$fragments+=$nav
}
$fragments+=$failedAutoStart | Select Name,Displayname,StartMode,State |
ConvertTo-Html -Fragment -PreContent ("" -f $computername.ToUpper())
$fragments+=$nav
$fragments+=$diskdata | ConvertTo-HTML -Fragment -PreContent ("" -f $computername.ToUpper())
$fragments+=$nav
#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 ("" -f $computername.ToUpper())
$fragments+=$nav
$fragments+=$syslogData | ConvertTo-HTML -Fragment -PreContent ("" -f $computername.toUpper())
$fragments+=$nav
$fragments+=$applogData | ConvertTo-HTML -Fragment -PreContent ("" -f $computername.toUpper())
$fragments+=$nav
}
elseif ($TEXT) {
#prepare formatted text
$ReportTitle
"-"*($ReportTitle.Length)
"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 @{
OperatingSystem=$osdata
ComputerSystem=$csdata
Services=$services.keys | foreach {$services.$_ | Select Name,Displayname,StartMode,State}
FailedAutoStart=$failedAutoStart | Select Name,Displayname,StartMode,State
Disks=$diskData
Network=$nicData
SystemLog=$syslogdata
ApplicationLog=$applogdata
ReportVersion=$reportVersion
RunDate=Get-Date
RunBy="$env:USERDOMAIN\$env:USERNAME"
}
}
} #if OK
else {
#can't ping computer so fail
Write-Warning "Failed to ping $computername"
}
} #process
End {
#if HTML finish the report here so that if piping in
#computer names we get one report for all computers
If ($HTML) {
#copying fragments to clipboard for troubleshooting
#Write $fragments | clip
$head+="
"
ConvertTo-Html -Head $head -Title $ReportTitle -PreContent ($fragments | out-String) -PostContent "
$footer"
}
Write-Host "Finished!" -ForegroundColor Green
}
#end of script