This script can be pointed at a list of servers in a text file, and the Event logs are scanned for application hang/crash events. The Windows Application hang event only occurs when an app hangs and user terminates the program. Also if werfault.exe is prevented from running, these event logs won’t be generated. (Windows Error Reporting disabled is OK, I am referring to actually preventing the EXE from running)
Example PDF report: https://onedrive.live.com/redir?resid=E1A3C870740A073D!19859&authkey=!AMDWrh0d5EidnkI&ithint=file%2cpdf
Script can be downloaded here: https://onedrive.live.com/redir?resid=E1A3C870740A073D!23156&authkey=!AGQdN-cPbNXJs2A&ithint=file%2czip
This script requires:
The parameters:
customer – Specify a customer name or description
reportFolder – Path to save HTML/PDF to
NumberOfDays – How many days back to report (default 30)
serverList – If blank will be local computer. Otherwise a text file with list of computers, or a CSV file with
two columns if you want to add a description of computer in 2nd column
reportFormat – default is PDF. Anything else will export in HTML
timeToLiveSeconds – The ping time to wait before skipping computer. Default 1 second
eventLogTimeOutSeconds – The time to wait for remote event log to respond before skipping computer
cleanUpImages – Default is TRUE. Deletes the PNG chart images created.
Note: The PIE charts don’t show items <5% this can be changed by modifying [“CollectedThreshold”]=5
<# .Synopsis Generates a PDF or HTML report of application hangs/crashes in event logs. .Notes AUTHOR: chentiangemalc LASTEDIT: Sept. 11, 2014 KEYWORDS: App Crash HTML Reporting .Link http://chentiangemalc.wordpress.com #Requires -Version 3.0 #> [CmdletBinding()] Param( [string]$customer = “”, [Parameter(Mandatory=$true)] [string]$reportFolder, [int]$NumberOfDays = 30, [string]$serverList =“”, [string]$reportFormat=“PDF“, [int]$TimeToLiveSeconds=1, [int]$EventLogTimeOutSeconds=1, [switch]$cleanUpImages = $true ) # Load .NET Chart Controls http://www.microsoft.com/en-us/download/details.aspx?id=14422 [void][Reflection.Assembly]::LoadWithPartialName(“System.Windows.Forms.DataVisualization“) # reporting time period $timespan = New–Object System.TimeSpan($NumberOfDays,0,0,0) # current directory – used later to launch PDF generator $curDir=Split–Path –Parent $MyInvocation.MyCommand.Definition # build our report name if (![String]::IsNullOrEmpty($customer)) { $reportName = [String]::Format(“$customer-AppCrash-{0:yyyy-MM-dd_hh-mm-ss-tt}“,[DateTime]::Now) } else { $reportName = [String]::Format(“AppCrash-{0:yyyy-MM-dd_hh-mm-ss-tt}“,[DateTime]::Now) } # Built our XPath format Event Log Queries # We will later replace milliseconds field with how far back we want to go $xpath_hang = @‘ <QueryList> <Query Id=“0“ Path=“Application“> <Select Path=“Application“> *[System[Provider[@Name=‘Application Hang’] and (EventID=1002) and TimeCreated[timediff(@SystemTime) <= milliseconds ]]] </Select> </Query> </QueryList> ‘@ $xpath_crash = @‘ <QueryList> <Query Id=“0“ Path=“Application“> <Select Path=“Application“> *[System[Provider[@Name=‘Application Error’] and (EventID=1000) and TimeCreated[timediff(@SystemTime) <= milliseconds]]] </Select> </Query> </QueryList> ‘@ $xpath_reboot = @‘ <QueryList> <Query Id=“0“ Path=“System“> <Select Path=“System“> *[System[(EventID=6005) and TimeCreated[timediff(@SystemTime) <= milliseconds]]] </Select> </Query> </QueryList> ‘@ $xpath_critical = @‘ <QueryList> <Query Id=“0“ Path=“System“> <Select Path=“System“>*[System[(Level=1 ) and TimeCreated[timediff(@SystemTime) <= milliseconds]]]</Select> </Query> </QueryList> ‘@ $cssStyle= @‘ <style type=“text/css“> * { margin: 0; padding: 0; } body { font: 14px/1.4 Calibri; } #page-wrap { margin: 50px; } p { margin: 20px 0; } H1 { font–size:36px; margin–top:5px; margin–bottom:15px; } H2 { font–size:18px; margin–top:20px; margin–bottom:10px; } H3 { font–size:14px; margin–top:1px; margin–bottom:5px; } /* Generic Styling, for Desktops/Laptops */ table { width: 100%; border–collapse: collapse; } /* Zebra striping */ tr:nth–of–type(odd) { background: #eee; } th { background: #333; color: white; font–weight: bold; } td, th { padding: 6px; border: 1px solid #ccc; text–align: left; vertical–align: top; } </style> ‘@ $xpath_hang = $xpath_hang.Replace(“milliseconds“,$timespan.TotalMilliseconds) $xpath_crash = $xpath_crash.Replace(“milliseconds“,$timespan.TotalMilliseconds) $xpath_reboot = $xpath_crash.Replace(“milliseconds“,$timespan.TotalMilliseconds) $xpath_critical = $xpath_critical.Replace(“milliseconds“,$timespan.TotalMilliseconds) $total_crash=@() $total_hang=@() $total_reboot=@() $total_critical=@() $computers =@() $table = New–Object System.Data.DataTable $table.Columns.Add(“Computer“) $table.Columns.Add(“Description“) $table.Columns.Add(“OS“) $table.Columns.Add(“Crash Count“) $table.Columns.Add(“Hang Count“) $table.Columns.Add(“Reboot History“) $table.Columns.Add(“Uptime“) $failedmachines=@{} $uptime=@{} $csvdata=$null if ([String]::IsNullOrEmpty($serverList)) { $computers+=$env:COMPUTERNAME } else { if ($serverList.EndsWith(“.csv“)) { $csvdata=Import–Csv $serverList ForEach ($line in $csvdata) { $computers+=$line.Computer } } else { $sr=New–Object System.IO.StreamReader($serverList) while (!$sr.EndOfStream) { $computers+=$sr.ReadLine().Trim() } } } $day=[System.DateTime]::Now.AddDays(–$timespan.TotalDays) $start_date=[System.DateTime]::Now.AddDays(–$timespan.TotalDays) $yesterday=[System.DateTime]::Now.AddDays(–1).Date $daily_crash=@{} $daily_hang=@{} $server_crash=@{} $server_hang=@{} $category_crash=@{} $category_hang=@{} $category_yesterdaycrash=@{} $category_yesterdayhang=@{} $process_crash=@{} $process_hang=@{} $total_criticalPerServer=@{} $category_server_crash=@{} $category_server_hang=@{} $missing_events=@{} $hour_crash=@{} $hour_hang=@{} $day_crash=@{} $day_hang=@{} $operatingSystem=@{} $rebootList=@{} $shortstart=$start_date.ToString(“dd/MM/yyyy“) $shortend = [System.DateTime]::Now.AddDays(–1).ToString(“dd/MM/yyyy“) while ($day -lt [System.DateTime]::Now) { $day=$day.AddDays(1) $short_date=$day.ToString(“dd/MM/yyyy“) $daily_crash[$short_date]=0 $daily_hang[$short_date]=0 } [System.DateTime]::Now.DayOfWeek $hour_crash=@{} $hour_hang=@{} for ($i=0; $i -lt 24; $i++) { $time=[System.DateTime]::Today.AddHours($i).ToString(“hh:mm tt“) $hour_crash[$time]=0 $hour_hang[$time]=0 } $currentCulture=[System.Globalization.CultureInfo]::CurrentCulture ForEach ($day in $currentCulture.DateTimeFormat.DayNames) { $day_crash[$day]=0 $day_hang[$day]=0 } ForEach ($computer in $computers) { “Checking if $computer is online…“ if(Test–Connection –Cn $computer –BufferSize 16 –TimeToLive $TimeToLiveSeconds –Count 1 –Quiet) { try { “$computer is online“ # launch process first to make sure connecting to event log doesn’t hang # this is because if a machine is online but Windows can’t connect to event log # and also doesn’t get back error (like Access Denied) Get-WinEvent will hang entire script $psi=New–Object System.Diagnostics.ProcessStartInfo(“PowerShell.exe“,“Get-WinEvent -ComputerName $computer -LogName Application -Oldest -MaxEvents 1“) $psi.UseShellExecute=$false $p=[System.Diagnostics.Process]::Start($psi) if ($p.WaitForExit($EventLogTimeOutSeconds * 1000)) { $oldestEvent=Get–WinEvent –ComputerName $computer –LogName Application –Oldest –MaxEvents 1 [String]::Format(“Oldest event is {0}“,$oldestEvent.TimeCreated.ToString(“F“)) } else { $p.Kill() $failedmachines[$computer]=“Couldn’t connect to event log within $eventLogResponse sec“ } } catch { $failedmachines[$computer] = $_.Exception.Message } if ($oldestEvent -ne $null) { if ($oldestEvent.TimeCreated -gt $start_date) { $missing_events[$computer]=$oldestEvent.TimeCreated.ToString(“F“) } try { try { $os=Get–WmiObject Win32_OperatingSystem –ComputerName $computer $operatingSystem[$computer]=$os.Caption $timespan = $os.ConvertToDateTime($os.LocalDateTime)–$os.ConvertToDateTime($os.LastBootUpTime) $uptime[$computer] = “$($timespan.Days) days $($timespan.Hours) hrs“ } catch { “Unable to query remote OS Error : $($_.Exception.Message)“ } “Processing Application Crashes from $computer“ $total_crash+=Get–WinEvent –ComputerName $computer –LogName Application –FilterXPath $xpath_crash –Oldest –ErrorAction SilentlyContinue “Processing Application Hangs from $computer“ $total_hang+=Get–WinEvent –ComputerName $computer –LogName Application –FilterXPath $xpath_hang –Oldest –ErrorAction SilentlyContinue “Processing Reboots from $computer“ $total_reboot+=Get–WinEvent –ComputerName $computer –LogName System –FilterXPath $xpath_reboot –Oldest –ErrorAction SilentlyContinue “Critical Events“ $total_critical+=Get–WinEvent –ComputerName $computer –LogName System –FilterXPath $xpath_critical –Oldest –ErrorAction SilentlyContinue } catch { $failedmachines[$computer] = $_.Exception.Message } } } else { $failedmachines[$computer]=“Machine is offline“ } } ForEach ($event in $total_critical) { $computer=$event.MachineName if (![String]::IsNullOrEmpty($computer)) { try { if ($computer.Contains(“.“)) { $computer=$computer.Substring(0,$computer.IndexOf(“.“)) } if ($total_criticalPerServer[$computer] -eq $null) { $total_criticalPerServer[$computer]=@{} } $total_criticalPerServer[$computer][$event.Message]++ } catch { $_ } } } ForEach ($event in $total_reboot) { $computer=$event.MachineName if (![String]::IsNullOrEmpty($computer)) { try { if ($computer.Contains(“.“)) { $computer=$computer.Substring(0,$computer.IndexOf(“.“)) } if ($rebootList[$computer] -eq $null) { $rebootList[$computer]=@() } $rebootList[$computer]+=$event.TimeCreated.ToString(“F“) } catch { $_ } } } ForEach ($event in $total_crash) { $computer=$event.MachineName $computer=$event.MachineName if (![String]::IsNullOrEmpty($computer)) { try { if ($computer.Contains(“.“)) { $computer=$computer.Substring(0,$computer.IndexOf(“.“)) } # crashes per day $short_date=$event.TimeCreated.ToString(“dd/MM/yyyy“) $time=[System.DateTime]::Today.AddHours($event.TimeCreated.Hour).ToString(“hh:mm tt“) $hour_crash[$time]++ $day = $event.TimeCreated.DayOfWeek.ToString() $day_crash[$day]++ $daily_crash[$short_date]++ # crashes per server $server_crash[$computer]++ # crashes per type $app=$event.Properties[0].Value $ver=$event.Properties[1].Value $module=$event.Properties[3].Value $modulever=$event.Properties[4].Value $exp=$event.Properties[6].Value $bucketID=“$app v$ver fault in $module v$modulever Exception $exp)“ $category_crash[$bucketID]++ if ($category_server_crash[$computer] -eq $null) { $category_server_crash[$computer]=@{} } if ($event.TimeCreated -ge $yesterday) { $category_yesterdaycrash[$bucketID]++ } $category_server_crash[$computer][$bucketID]++ $process_crash[$app]++ } catch { $_ } } } ForEach ($event in $total_hang) { $computer=$event.MachineName if ($computer.Contains(“.“)) { $computer=$computer.Substring(0,$computer.IndexOf(“.“)) } # crashes per day $short_date=$event.TimeCreated.ToString(“dd/MM/yyyy“) $daily_hang[$short_date]++ $time=[System.DateTime]::Today.AddHours($event.TimeCreated.Hour).ToString(“hh:mm tt“) $hour_hang[$time]++ $day = $event.TimeCreated.DayOfWeek.ToString() $day_hang[$day]++ $daily_crash[$short_date]++ # crashes per server $server_hang[$computer]++ # crashes per type $app=$event.Properties[0].Value $ver=$event.Properties[1].Value $bucketID=“$app v$ver“ $category_hang[$bucketID]++ $bucketID if ($category_server_hang[$computer] -eq $null) { $category_server_hang[$computer]=@{} } if ($event.TimeCreated -ge $yesterday) { $category_yesterdayhang[$bucketID]++ } $category_server_hang[$computer][$bucketID]++ $process_hang[$app]++ } # build report # crashes since yesterday $html_yesterday=“<h2>Crashes Since Yesterday</h2>“ if ($category_yesterdaycrash.Count -gt 0) { $html_yesterday+=$category_yesterdaycrash.GetEnumerator() | Sort–Object Value –Descending | Select–Object Name,Value | ConvertTo–Html –Fragment } else { $html_yesterday+=“<p>None</p>“ } $html_yesterday+=“<h2>Hangs Since Yesterday</h2>“ if ($category_yesterdayhang.Count -gt 0) { $html_yesterday+=$category_yesterdayhang.GetEnumerator() | Sort–Object Value –Descending | Select–Object Name,Value | ConvertTo–Html –Fragment } else { $html_yesterday+=“<p>None</p>“ } # per server “Crash per server“ $html_server_crash =“<h2>Crashes Per Server</h2>“ $html_server_crash+= $server_crash.GetEnumerator() | Sort–Object Value –Descending | Select–Object Name,Value | ConvertTo–Html –Fragment $html_server_Hang = “<h2>Hangs Per Server</h2>“ $html_server_Hang += $server_hang.GetEnumerator() | Sort–Object Value –Descending | Select–Object Name,Value | ConvertTo–Html –Fragment # per type “Crashes By Category“ $html_category_crash =“<h2>Crashes By Category</h2>“ $html_category_crash+=$category_crash.GetEnumerator() | Sort–Object Value –Descending | Select–Object Name,Value | ConvertTo–Html –Fragment “” # per type “Hangs by Application“ $html_category_hang =“<h2>Hangs by Application</h2>“ $html_category_hang+=$category_hang.GetEnumerator() | Sort–Object Value –Descending | Select–Object Name,Value | ConvertTo–Html –Fragment “” “Crashes Category Per Server“ $html_server = “<h2>Crashes Category Per Server</h2>“ ForEach ($server in $server_crash | Sort–Object Value –Descending) { “Crash Breakdown for $($server.Keys)“ if ($category_server_crash[$($server.Keys)].Count -gt 0) { $html_server+= “<h3>$($server.Keys)</h3>“ $html_server+=$category_server_crash[$($server.Keys)].GetEnumerator() | Sort–Object Value –Descending | Select–Object Name,Value | ConvertTo–Html –Fragment } else { $html_server+= “<h3>$($server.Keys)</h3><p>None</p>“ } } “Hang Category Per Server“ $html_server += “<h2>Hung Process Per Server</h2>“ ForEach ($server in $server_hang | Sort–Object Value –Descending) { “Crash Breakdown for $($server.Keys)“ if ($category_server_hang[$($server.Keys)].Count -gt 0) { $html_server+= “<h3>$($server.Keys)</h3>“ $html_server+=$category_server_hang[$($server.Keys)].GetEnumerator() | Sort–Object Value –Descending | Select–Object Name,Value | ConvertTo–Html –Fragment } else { $html_server+= “<h3>$($server.Keys)</h3><p>None</p>“ } } “Critical Events Per Server“ $html_server+=“<h2>Critical Events Per Server</h2>“ if ($total_criticalPerServer.Count -eq 0) { $html_server+=“<p>None</p>“ } else { ForEach ($item in $total_criticalPerServer) { if ($item.Values.Count -gt 0) { $html_server+= “<h3>$($item.Keys)</h3>“ $html_server+=$total_criticalPerServer[$($item.Keys)].GetEnumerator() | Sort–Object Value –Descending | Select–Object Name,Value | ConvertTo–Html –Fragment } } } “Missing Events Per Server“ if ($missing_events.Count -gt 0) { $html_server+=“<h2>Events Missing From Server</h2>“ $html_server+=“<p>These servers oldest event logs are newer than start date of report.</p>“ $html_server+=$missing_events.GetEnumerator() | Select–Object Name,Value | ConvertTo–Html –Fragment } if ($failedmachines.Count -gt 0) { $html_server+=“<h2>Errors Connecting To Servers</h2>“ $html_server+=$failedmachines.GetEnumerator() | Select–Object Name,Value | ConvertTo–Html –Fragment } # build chart # build chart $page1ChartHeight = 660 $otherPagesChartHeight = 690 # *** DAILY CRASH TREND CHART = CHART1 $dailyCrashTrendChart = New–object System.Windows.Forms.DataVisualization.Charting.Chart $dailyCrashTrendChart.Width = 1024 $dailyCrashTrendChart.Height = $page1ChartHeight $dailyCrashTrendChart.BackColor = [System.Drawing.Color]::White [void]$dailyCrashTrendChart.Titles.Add(“Daily Crash Trend“) $dailyCrashTrendChart.Titles[0].Font = “Arial,13pt“ $dailyCrashTrendChart.Titles[0].Alignment = “topLeft“ $chartarea = New–Object System.Windows.Forms.DataVisualization.Charting.ChartArea $chartarea.Name = “ChartArea1“ $chartarea.AxisY.Title = “Crash Count“ $chartarea.AxisX.Title = “Date“ $chartarea.AxisY.Interval =($daily_crash.GetEnumerator() | Sort–Object Value –Descending)[0].Value $chartarea.AxisX.Interval = 1 $dailyCrashTrendChart.ChartAreas.Add($chartarea) [void]$dailyCrashTrendChart.Series.Add(“CrashCount“) $dailyCrashTrendChart.Series[“CrashCount“].ChartType = “Line“ $dailyCrashTrendChart.Series[“CrashCount“].BorderWidth = 3 $dailyCrashTrendChart.Series[“CrashCount“].IsVisibleInLegend = $true $dailyCrashTrendChart.Series[“CrashCount“].chartarea = “ChartArea1“ $dailyCrashTrendChart.Series[“CrashCount“].color = “#62B5CC“ $day=$start_date while ($day -lt [System.DateTime]::Now) { $day=$day.AddDays(1) $short_date=$day.ToString(“dd/MM/yyyy“) “Process crash chart for $day“ if ($daily_crash[$short_date] -ne $null) { [Void]$dailyCrashTrendChart.Series[“CrashCount“].Points.addxy( $short_date , $daily_crash[$short_date]) } } $dailyCrashTrendChartfilename=[System.IO.Path]::Combine($reportFolder,“$reportName-Chart1.png“) $dailyCrashTrendChart.SaveImage($dailyCrashTrendChartfilename,“png“) # build chart # build chart $dailyHangTrendChart = New–object System.Windows.Forms.DataVisualization.Charting.Chart $dailyHangTrendChart.Width = 1024 $dailyHangTrendChart.Height = $page1ChartHeight $dailyHangTrendChart.BackColor = [System.Drawing.Color]::White [void]$dailyHangTrendChart.Titles.Add(“Daily Hang Trend“) $dailyHangTrendChart.Titles[0].Font = “Arial,13pt“ $dailyHangTrendChart.Titles[0].Alignment = “topLeft“ $chartarea = New–Object System.Windows.Forms.DataVisualization.Charting.ChartArea $chartarea.Name = “ChartArea1“ $chartarea.AxisY.Title = “Hang Count“ $chartarea.AxisX.Title = “Date“ $chartarea.AxisY.Interval =($daily_hang.GetEnumerator() | Sort–Object Value –Descending)[0].Value $chartarea.AxisX.Interval = 1 $dailyHangTrendChart.ChartAreas.Add($chartarea) [void]$dailyHangTrendChart.Series.Add(“CrashCount“) $dailyHangTrendChart.Series[“CrashCount“].ChartType = “Line“ $dailyHangTrendChart.Series[“CrashCount“].BorderWidth = 3 $dailyHangTrendChart.Series[“CrashCount“].IsVisibleInLegend = $true $dailyHangTrendChart.Series[“CrashCount“].chartarea = “ChartArea1“ $dailyHangTrendChart.Series[“CrashCount“].color = “#62B5CC“ $day=$start_date while ($day -lt [System.DateTime]::Now) { $day=$day.AddDays(1) $short_date=$day.ToString(“dd/MM/yyyy“) if ($daily_hang[$short_date] -ne $null) { [Void]$dailyHangTrendChart.Series[“CrashCount“].Points.addxy( $short_date , $daily_hang[$short_date]) } } $dailyHangTrendChartfilename=[System.IO.Path]::Combine($reportFolder,“$reportName-chart3.png“) $dailyHangTrendChart.SaveImage($dailyHangTrendChartfilename,“png“) $processCrashChart = New–Object System.Windows.Forms.DataVisualization.Charting.Chart $processCrashChart.Width = 1024 $processCrashChart.Height =$otherPagesChartHeight $processCrashChart.BackColor = [System.Drawing.Color]::White [void]$processCrashChart.Titles.Add(“Crash by Process“) $processCrashChart.Titles[0].Font = “Arial,13pt“ $processCrashChart.Titles[0].Alignment = “topLeft“ $chartarea = New–Object System.Windows.Forms.DataVisualization.Charting.ChartArea $chartarea.Name = “ChartArea1“ $chartarea.AxisY.Title = “Process“ $chartarea.AxisX.Title = “Data“ #$chartarea.AxisY.Interval =($daily_hang.GetEnumerator() | Sort-Object Value -Descending)[0].Value #$chartarea.AxisX.Interval = 1 $processCrashChart.ChartAreas.Add($chartarea) [void]$processCrashChart.Series.Add(“Process“) $processCrashChart.Series[“Process“].ChartType = “Pie“ $processCrashChart.Series[“Process“][“PieLabelStyle“]=“Outside“ $processCrashChart.Series[“Process“][“CollectedThreshold“]=5 $processCrashChart.Series[“Process“][“CollectedThresholdUsePercent“]=$true $processCrashChart.Series[“Process“].BorderWidth = 1 $processCrashChart.Series[“Process“].BorderColor = [System.Drawing.Color]::FromArgb(26, 59, 105); $processCrashChart.Series[“Process“].IsVisibleInLegend = $true $processCrashChart.Series[“Process“].chartarea = “ChartArea1“ $processCrashChart.Series[“Process“].color = “#62B5CC“ ForEach ($process in $process_crash.GetEnumerator()) { $processCrashChart.Series[“Process“].Points.addxy( $process.Key, $process.Value) } $processCrashChartfilename=[System.IO.Path]::Combine($reportFolder,“$reportName-Chart2.png“) $processCrashChart.SaveImage($processCrashChartfilename,“png“) $processHangChart = New–Object System.Windows.Forms.DataVisualization.Charting.Chart $processHangChart.Width = 1024 $processHangChart.Height = $otherPagesChartHeight $processHangChart.BackColor = [System.Drawing.Color]::White [void]$processHangChart.Titles.Add(“Hang by Process“) $processHangChart.Titles[0].Font = “Arial,13pt“ $processHangChart.Titles[0].Alignment = “topLeft“ $chartarea = New–Object System.Windows.Forms.DataVisualization.Charting.ChartArea $chartarea.Name = “ChartArea1“ $chartarea.AxisY.Title = “Process“ $chartarea.AxisX.Title = “Date“ $chartarea.AxisY.Interval =($daily_crash.GetEnumerator() | Sort–Object Value –Descending)[0].Value $chartarea.AxisX.Interval = 1 $processHangChart.ChartAreas.Add($chartarea) [void]$processHangChart.Series.Add(“Process“) $processHangChart.Series[“Process“].ChartType = “Pie“ $processHangChart.Series[“Process“][“PieLabelStyle“]=“Outside“ $processHangChart.Series[“Process“][“CollectedThreshold“]=5 $processHangChart.Series[“Process“][“CollectedThresholdUsePercent“]=$true $processHangChart.Series[“Process“].BorderWidth = 1 $processHangChart.Series[“Process“].BorderColor = [System.Drawing.Color]::FromArgb(26, 59, 105); $processHangChart.Series[“Process“].IsVisibleInLegend = $true $processHangChart.Series[“Process“].chartarea = “ChartArea1“ $processHangChart.Series[“Process“].color = “#62B5CC“ ForEach ($process in $process_hang.GetEnumerator()) { $processHangChart.Series[“Process“].Points.addxy( $process.Key, $process.Value) } $processHangChartfilename=[System.IO.Path]::Combine($reportFolder,“$reportName-Chart4.png“) $processHangChart.SaveImage($processHangChartfilename,“png“) # *** DAILY CRASH TREND CHART = CHART1 $hourlyCrashTrendChart = New–object System.Windows.Forms.DataVisualization.Charting.Chart $hourlyCrashTrendChart.Width = 1024 $hourlyCrashTrendChart.Height = $otherPagesChartHeight $hourlyCrashTrendChart.BackColor = [System.Drawing.Color]::White [void]$hourlyCrashTrendChart.Titles.Add(“Hourly Crash Trend“) $hourlyCrashTrendChart.Titles[0].Font = “Arial,13pt“ $hourlyCrashTrendChart.Titles[0].Alignment = “topLeft“ $chartarea = New–Object System.Windows.Forms.DataVisualization.Charting.ChartArea $chartarea.Name = “ChartArea1“ $chartarea.AxisY.Title = “Crash Count“ $chartarea.AxisX.Title = “Date“ $chartarea.AxisY.Interval =($hour_crash.GetEnumerator() | Sort–Object Value –Descending)[0].Value $chartarea.AxisX.Interval = 1 $hourlyCrashTrendChart.ChartAreas.Add($chartarea) [void]$hourlyCrashTrendChart.Series.Add(“CrashCount“) $hourlyCrashTrendChart.Series[“CrashCount“].ChartType = “Line“ $hourlyCrashTrendChart.Series[“CrashCount“].BorderWidth = 3 $hourlyCrashTrendChart.Series[“CrashCount“].IsVisibleInLegend = $true $hourlyCrashTrendChart.Series[“CrashCount“].chartarea = “ChartArea1“ $hourlyCrashTrendChart.Series[“CrashCount“].color = “#62B5CC“ for ($i=0; $i -lt 24 ; $i++) { $time=[System.DateTime]::Today.AddHours($i).ToString(“hh:mm tt“) [Void]$hourlyCrashTrendChart.Series[“CrashCount“].Points.addxy( $time , $hour_crash[$time]) } $hourlyCrashTrendChartfilename=[System.IO.Path]::Combine($reportFolder,“$reportName-HourlyCrashTrend.png“) $hourlyCrashTrendChart.SaveImage($hourlyCrashTrendChartfilename,“png“) $day_crashTrendChart = New–object System.Windows.Forms.DataVisualization.Charting.Chart $day_crashTrendChart.Width = 1024 $day_crashTrendChart.Height = $otherPagesChartHeight $day_crashTrendChart.BackColor = [System.Drawing.Color]::White [void]$day_crashTrendChart.Titles.Add(“Day Of Week Crash Trend“) $day_crashTrendChart.Titles[0].Font = “Arial,13pt“ $day_crashTrendChart.Titles[0].Alignment = “topLeft“ $chartarea = New–Object System.Windows.Forms.DataVisualization.Charting.ChartArea $chartarea.Name = “ChartArea1“ $chartarea.AxisY.Title = “Crash Count“ $chartarea.AxisX.Title = “Date“ $chartarea.AxisY.Interval =($hour_crash.GetEnumerator() | Sort–Object Value –Descending)[0].Value $chartarea.AxisX.Interval = 1 $day_crashTrendChart.ChartAreas.Add($chartarea) [void]$day_crashTrendChart.Series.Add(“CrashCount“) $day_crashTrendChart.Series[“CrashCount“].ChartType = “Line“ $day_crashTrendChart.Series[“CrashCount“].BorderWidth = 3 $day_crashTrendChart.Series[“CrashCount“].IsVisibleInLegend = $true $day_crashTrendChart.Series[“CrashCount“].chartarea = “ChartArea1“ $day_crashTrendChart.Series[“CrashCount“].color = “#62B5CC“ ForEach ($day in $currentCulture.DateTimeFormat.DayNames) { [Void]$day_crashTrendChart.Series[“CrashCount“].Points.addxy( $day , $day_crash[$day]) } $day_crashTrendChartfilename=[System.IO.Path]::Combine($reportFolder,“$reportName-dayofweekCrashTrend.png“) $day_crashTrendChart.SaveImage($day_crashTrendChartfilename,“png“) # *** DAILY Hang TREND CHART = CHART1 $hourlyHangTrendChart = New–object System.Windows.Forms.DataVisualization.Charting.Chart $hourlyHangTrendChart.Width = 1024 $hourlyHangTrendChart.Height = $otherPagesChartHeight $hourlyHangTrendChart.BackColor = [System.Drawing.Color]::White [void]$hourlyHangTrendChart.Titles.Add(“Hourly Hang Trend“) $hourlyHangTrendChart.Titles[0].Font = “Arial,13pt“ $hourlyHangTrendChart.Titles[0].Alignment = “topLeft“ $chartarea = New–Object System.Windows.Forms.DataVisualization.Charting.ChartArea $chartarea.Name = “ChartArea1“ $chartarea.AxisY.Title = “Hang Count“ $chartarea.AxisX.Title = “Date“ $chartarea.AxisY.Interval =($hour_hang.GetEnumerator() | Sort–Object Value –Descending)[0].Value $chartarea.AxisX.Interval = 1 $hourlyHangTrendChart.ChartAreas.Add($chartarea) [void]$hourlyHangTrendChart.Series.Add(“HangCount“) $hourlyHangTrendChart.Series[“HangCount“].ChartType = “Line“ $hourlyHangTrendChart.Series[“HangCount“].BorderWidth = 3 $hourlyHangTrendChart.Series[“HangCount“].IsVisibleInLegend = $true $hourlyHangTrendChart.Series[“HangCount“].chartarea = “ChartArea1“ $hourlyHangTrendChart.Series[“HangCount“].color = “#62B5CC“ for ($i=0; $i -lt 24 ; $i++) { $time=[System.DateTime]::Today.AddHours($i).ToString(“hh:mm tt“) [Void]$hourlyHangTrendChart.Series[“HangCount“].Points.addxy( $time , $hour_hang[$time]) } $hourlyHangTrendChartfilename=[System.IO.Path]::Combine($reportFolder,“$reportName-HourlyHangTrend.png“) $hourlyHangTrendChart.SaveImage($hourlyHangTrendChartfilename,“png“) $day_hangTrendChart = New–object System.Windows.Forms.DataVisualization.Charting.Chart $day_hangTrendChart.Width = 1024 $day_hangTrendChart.Height = $otherPagesChartHeight $day_hangTrendChart.BackColor = [System.Drawing.Color]::White [void]$day_hangTrendChart.Titles.Add(“Day of Week Hang Trend“) $day_hangTrendChart.Titles[0].Font = “Arial,13pt“ $day_hangTrendChart.Titles[0].Alignment = “topLeft“ $chartarea = New–Object System.Windows.Forms.DataVisualization.Charting.ChartArea $chartarea.Name = “ChartArea1“ $chartarea.AxisY.Title = “Hang Count“ $chartarea.AxisX.Title = “Date“ $chartarea.AxisY.Interval =($hour_hang.GetEnumerator() | Sort–Object Value –Descending)[0].Value $chartarea.AxisX.Interval = 1 $day_hangTrendChart.ChartAreas.Add($chartarea) [void]$day_hangTrendChart.Series.Add(“HangCount“) $day_hangTrendChart.Series[“HangCount“].ChartType = “Line“ $day_hangTrendChart.Series[“HangCount“].BorderWidth = 3 $day_hangTrendChart.Series[“HangCount“].IsVisibleInLegend = $true $day_hangTrendChart.Series[“HangCount“].chartarea = “ChartArea1“ $day_hangTrendChart.Series[“HangCount“].color = “#62B5CC“ ForEach ($day in $currentCulture.DateTimeFormat.DayNames) { [Void]$day_hangTrendChart.Series[“HangCount“].Points.addxy( $day , $day_hang[$day]) } $day_hangTrendChartfilename=[System.IO.Path]::Combine($reportFolder,“$reportName-dayofweekHangTrend.png“) $day_hangTrendChart.SaveImage($day_hangTrendChartfilename,“png“) $charts = “<h2>Total Application Crashes Per Day</h2>“ $charts+=[String]::Format(‘<img src=“{0}-Chart1.png“>‘,[System.IO.Path]::Combine($reportFolder,$reportName)) $charts+=“<h2>Total Application Hangs Per Day</h2>“ $charts+=[String]::Format(‘<img src=“{0}-Chart3.png“>‘,[System.IO.Path]::Combine($reportFolder,$reportName)) $charts+=“<h2>Total Application Crashes Per Hour</h2>“ $charts+=[String]::Format(‘<img src=“{0}“>‘,$hourlyCrashTrendChartfilename) $charts+=“<h2>Total Application Hang Per Hour</h2>“ $charts+=[String]::Format(‘<img src=“{0}“>‘,$hourlyHangTrendChartfilename) $charts+=“<h2>Total Application Crashes Per Day of Week</h2>“ $charts+=[String]::Format(‘<img src=“{0}“>‘,$day_crashTrendChartfilename) $charts+=“<h2>Total Application Hangs Per Day of Week</h2>“ $charts+=[String]::Format(‘<img src=“{0}“>‘,$day_hangTrendChartfilename) $charts+=“<h2>Process Crash Breakdown</h2>“ $charts+=[String]::Format(‘<img src=“{0}-Chart2.png“>‘,[System.IO.Path]::Combine($reportFolder,$reportName)) $charts+=“<h2>Process Hang Breakdown</h2>“ $charts+=[String]::Format(‘<img src=“{0}-Chart4.png“>‘,[System.IO.Path]::Combine($reportFolder,$reportName)) ForEach ($computer in $computers) { $computer=$computer.ToUpper() $desc=“” if ($csvdata -ne $null) { $desc=($csvdata | Where–Object {$_.Computer -eq $computer })[0].Description } $reboots=“” $computerReboots=$rebootList[$computer] if ($computerReboots.Count -gt 0) { ForEach ($reboot in $computerReboots) { $reboots+=“$($reboot)`r`n“ } } else { $reboots=“None“ } $table.Rows.Add( $computer, $desc, $operatingSystem[$computer], $server_crash[$computer], $server_hang[$computer], $reboots, $uptime[$computer]) } $html_server +=“<h2>Server Summary</h2>“ if ($csvdata -eq $null) { $html_table=$table | Select–Object Computer,OS,“Crash Count“,“Hang Count“,“Reboot History“,Uptime | ConvertTo–Html –Fragment } else { $html_table=$table | Select–Object Computer,Description,OS,“Crash Count“,“Hang Count“,“Reboot History“,Uptime | ConvertTo–Html –Fragment } $html_table=$html_table.Replace(“`r`n“,“<br>“) $html_server += $html_table $htmlFilename=[System.String]::Format(“{0}.html“,[System.IO.Path]::Combine($reportFolder,$reportName)) $pdfFilename=[System.String]::Format(“{0}.pdf“,[System.IO.Path]::Combine($reportFolder,$reportName)) if (![String]::IsNullOrEmpty($customer)) { $title = “<h1>Event Log Summary for $customer from $shortstart to $shortend </h1>“ } else { $title = “<h1>Event Log Summary from $shortstart to $shortend </h1>“ } ConvertTo–Html –Head $cssStyle –Body “$title $charts $html_yesterday $html_category_crash $html_category_hang $html_server_crash $html_server_Hang $html_server“ –Title “App Stability Report for $customer“ | Out-File $htmlFilename if ($reportFormat -eq “PDF“) { $argumentList=@() $argumentList+=$htmlFilename $argumentList+=$pdfFilename Start–Process –FilePath $curDir\wkhtmltopdf.exe –ArgumentList $argumentList –Wait Remove–Item $htmlFilename Write–Output “Report located at ‘$($pdfFilename)’“ } else { Write–Output “Report located at ‘$($htmlFilename)’“ } if ($cleanUpImages) { Remove–Item $dailyCrashTrendChartfilename Remove–Item $processCrashChartfilename Remove–Item $dailyHangTrendChartfilename Remove–Item $processHangChartfilename Remove–Item $hourlyCrashTrendChartfilename Remove–Item $hourlyHangTrendChartfilename Remove–Item $day_crashTrendChartfilename Remove–Item $day_hangTrendChartfilename }
About chentiangemalc
specializes in end-user computing technologies. disclaimer 1) use at your own risk. test any solution in your environment. if you do not understand the impact/consequences of what you're doing please stop, and ask advice from somebody who does. 2) views are my own at the time of posting and do not necessarily represent my current view or the view of my employer and family members/relatives. 3) over the years Microsoft/Citrix/VMWare have given me a few free shirts, pens, paper notebooks/etc. despite these gifts i will try to remain unbiased.