#requires -version 2.0
<#
.Synopsis
Create System Report
.Description
Create a system status report with information gathered from WMI. The default
output to the pipeline is a collection of custom objects. 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 either the text or html output.
NOTE: If you specify alternate credentials then any remote computers must have
PowerShell remoting enabled.
.Parameter Computername
The name of the computer to query. The default is the localhost.
.Parameter Credential
The name of an alternate credential, or a saved credential object.
.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. You must pipe to Out-File to save the results.
.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/2013 09:47:26
...Application Event Log Error/Warning since 01/09/2013 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/2013/02/powershell-morning-report-with-credentials
.Link
Get-WMIObject
Get-EventLog
ConvertTo-HTML
.Inputs
String
.Outputs
Custom object, text or HTML code
.Notes
Version : 2.0
Last Updated: 02/21/2013
Author : Jeffery Hicks (@JeffHicks)
Read PowerShell:
Learn Windows PowerShell 3 in a Month of Lunches
Learn PowerShell Toolmaking in a Month of Lunches
PowerShell in Depth: An Administrator's Guide
****************************************************************
* 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. *
****************************************************************
#>
[cmdletbinding(DefaultParameterSetName="object")]
Param(
[Parameter(Position=0,ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True)]
[ValidateNotNullOrEmpty()]
[string]$Computername=$env:computername,
[System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
[ValidateNotNullOrEmpty()]
[alias("title")]
[string]$ReportTitle="Morning 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="2.0"
<#
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
#>
#region define html head
$head = @"
$ReportTitle
The Morning Report
$(Get-Date -DisplayHint Date | out-string)
"@
#endregion
#prepare HTML code
$fragments=@()
} #Begin
Process {
#region ping test
#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
}
#endregion
#region define a parameter hashtable
$paramhash=@{
Classname="Win32_OperatingSystem"
Computername=$Computername
ErrorAction="Stop"
}
if ($credential) {
$paramhash.Add("Credential",$Credential)
}
#endregion
If ($OK) {
Try {
#get Operating system information from WMI
$os=Get-WmiObject @paramhash
#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
#region 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))}}
#endregion
#region Computer system
Write-Host "...Computer System" -ForegroundColor Cyan
$paramhash.Classname="Win32_ComputerSystem"
$cs=Get-WmiObject @paramhash
$csdata=$cs | Select Status,Manufacturer,Model,SystemType,Number*
#endregion
#region Get Service information
Write-Host "...Services" -ForegroundColor Cyan
#get services via WMI and group into a hash table
$paramhash.Classname="Win32_Service"
$wmiservices=Get-WmiObject @paramhash
$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")}
#endregion
#region Disk Utilization
Write-Host "...Logical Disks" -ForegroundColor Cyan
$paramhash.Classname="Win32_LogicalDisk"
$paramhash.Add("Filter","Drivetype=3")
$disks=Get-WmiObject @paramhash
$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)}}
#endregion
#region NetworkAdapters
Write-Host "...Network Adapters" -ForegroundColor Cyan
$paramhash.classname="Win32_NetworkAdapter"
$paramhash.filter="MACAddress Like '%'"
#get NICS that have a MAC address only
$nics=Get-WmiObject @paramhash
$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
}
#endregion
If ($Quick) {
Write-Verbose "Skipping event log queries"
}
#region Event log queries
else {
#Event log errors and warnings in the last $Hours hours
$last=(Get-Date).AddHours(-$Hours)
#define a hash table of parameters to splat to Get-Eventlog
$GetEventLogParam = @{
LogName="System"
EntryType="Error","Warning"
After=$last}
#System Log
Write-Host "...System Event Log Error/Warning since $last" -ForegroundColor Cyan
#hashtable of optional parameters for Invoke-Command
$InvokeCommandParam = @{
Computername=$Computername
ArgumentList=$GetEventLogParam
ScriptBlock = {Param ($params) Get-EventLog @params }
}
if ($Credential) { $InvokeCommandParam.Add("Credential",$Credential) }
$syslog = Invoke-Command @InvokeCommandParam
$syslogdata = $syslog | Select TimeGenerated,EventID,Source,Message
#Application Log
Write-Host "...Application Event Log Error/Warning since $last" -ForegroundColor Cyan
#update the hashtable
$GetEventLogParam.LogName="Application"
#update invoke-command parameters
$InvokeCommandParam.ArgumentList = $GetEventLogParam
$applog = Invoke-Command @InvokeCommandParam
$applogdata = $applog | Select TimeGenerated,EventID,Source,Message
}
#endregion
} #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
#region Create HTML
if ($HTML) {
#add each computer to a navigation menu in the header
$head+=("{0} " -f $computername.ToUpper())
$fragments+=("" -f $computername.ToUpper())
$fragments+=$osdata | ConvertTo-Html -as List -Fragment
$fragments+=$csdata | ConvertTo-Html -as List -Fragment
#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+=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
}
#endregion
#region Create TEXT
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
}
#endregion
#region Create custom object
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"
}
}
#endregion
} #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