The Powerscript below is a modular script that offers following functions:

  •  display the event log properties
  • analyse number of events per category
  • analyse number of events per severity
  • overview of error events with source, severity and sample message
  • detailed list of last event per eventID

You can configure the script:

  • choice of event logs
  • history length (period of events to report on)
  • enable/disable logging
  • enable/disable result export to file


You can download the script at:






#Do you want to enable transcript for logging all output to file?

$enableLogging = $TRUE

$ExportEnabled = $FALSE


# logging

# if you need detailed logging for troubleshooting this script, you can enable the transcript

# get the script location path and use it as default location for storing logs and results

$log = $MyInvocation.MyCommand.Definition -replace 'ps1','log'

$resultPath = $PSScriptRoot + '\'

Push-Location $resultPath


if ($enableLogging)


Start-Transcript -Path $log -ErrorAction SilentlyContinue

Write-Host "Logging enabled..."



Write-Host "Powershell version"








# Initialisation

# Source:

# As of 2104, there is a PowerShell bug in cultures such as "en-GB" or "en-DE",

# which prevents the display of the properties: 'LevelDisplayName' and 'Message'; here is a work-around

$currentCulture = [System.Threading.Thread]::CurrentThread.CurrentCulture


# Configuration

# selected Event log sources

# limit the feedback only to the following logs

$EventLogList = 'System','Application','Setup','Forefront Identity Manager','Forefront Identity Manager Management Agent'


#for FIM Health Check the Security log has less signification value and is skipped

#add it to the eventlog list when you need it



# if the event logs are containing too much data,

# powershell might not be able to load all due to memory limits


# return X week to collect logs

## startdate = ((Get-Date).AddDays(-7))

## $startdate = ((Get-Date).AddDays(-14))


#collect x month of logs

## $startdate = ((Get-Date).AddMonths(-1))


#collect x years of logs

$startdate = ((Get-Date).AddYears(-1))


## Background info

# We only need the non-informational event

# Verbose      5                                                                                                                                 

# Warning      3                                                                                                                                  

# Error        2                                                                                                                                 

# Critical     1                                                                                                                                  


# Informational and LogAlways is discarded


#Informational 4                                                                                                                                  

#LogAlways     0



Write-host "Event logs list"

Write-host "---------------"



#Displaying the log settings for the selected Event log list



Write-Host "Event Log Properties"

Write-Host "--------------------"


$Count = 0

$Activity = "Checking log properties"

foreach ($eventlog in $EventLogList)


    $count += 1

    $pct = ($Count / $EventLogList.Count * 100)

    Write-Progress -Activity $Activity -Status $EventLog -PercentComplete $pct


    #get all evenlogs from the list and display their properties


    $export = Get-WinEvent -ListLog $eventlog | Select-Object  -Property LogName,LogFilePath,LogType,RecordCount,MaximumSizeInBytes,FileSize,LastWriteTime,LastAccessTime,IsLogFull,Logmode




    #prep export

    $exportfile = $resultPath + "_props"+$eventlog + ".csv.txt"

    if ($exportEnabled)


        $export | Export-Csv $exportfile -NoTypeInformation



    #if you want all properties of the logs, replace the named attribute list with *

    #Get-WinEvent -ListLog $eventlog | Select-Object -Property *





$allEvents = New-Object System.Collections.Hashtable


$Count = 0

$Activity = "Checking log detaills"

foreach ($eventlog in $EventLogList)


    $Count += 1

    $pct = ($Count / $EventLogList.Count * 100)

    $status = $EventLog + " (" + $Count + "/" + $EventLogList.Count +")"

    Write-Progress -Activity $Activity -Status $status -PercentComplete $pct   

    write-host $count"." $eventlog


    [System.Threading.Thread]::CurrentThread.CurrentCulture = New-Object "System.Globalization.CultureInfo" "en-US"

    #if ($eventlog -eq 'System'){[System.Threading.Thread]::CurrentThread.CurrentCulture = $currentCulture}



    # query the event log

    # store the data in a hashtable, to avoid new queries

    $allEvents = $Null

    $allEvents = Get-WinEvent -FilterHashtable @{logname=$eventlog;StartTime=$startdate;level=0,1,2,3,4,5} -ErrorAction SilentlyContinue

    #DEBUG if ($eventlog -eq "Application") { $allevents}


    if ($allEvents.count -eq 0)


        $message = "No events for " + $eventlog + "log since "+ $startdate + "."

        Write-Host $message


        # no data to process, skip processing for current loop




    # Group by event type


    write-host "Group by Event type"

    write-host "-------------------"


    #display all events grouped by type and sorted by count

    $export = $allEvents | Group-Object -Property {$_.LevelDisplayName} -NoElement | Sort-Object Count -Descending 


    $export |  Format-Table -AutoSize  


    #prep export

    $exportfile = $resultPath + "_EventNameStats" + $eventlog + ".csv.txt"

    if ($exportEnabled) {$export | Select-Object -Property Count,Name |Export-Csv $exportfile}


    #detailed statistics for non-information events


    write-host "Statistics by Event ID"

    write-host "----------------------"


    #For events detailed reporting we're only interested in error events

    #not interested in informational events (level 0 and 4)

    $evtStats = $allEvents | where -Property level -Notin -Value 0,4 | Group-Object id | Sort-Object Count -Descending

    $allevents = $Null


    #display stats in table format

    $export = $evtStats | Select-Object Count,Name


    #$export | Format-Table -AutoSize



    #prep export

    $exportfile = $resultPath + "_EventIDStats"+ $eventlog + ".csv.txt"

    if ($exportEnabled) {$export | Export-Csv $exportfile  -NoTypeInformation}


    # evtStats has number and ID attribute

    # other attributes must be added:

    #  - errortype name

    #  - Source

    #  - errortype name


    [System.Collections.ArrayList]$results = @()


    # for each event id in the event statistics

    # display the most recent event

    $Activity = "Looking up last event occurrence..."


    $i= 0

    foreach ($item in $evtStats)


        $i += 1

        $pct = ($i / $evtStats.Count * 100)

        $eventID = $item.Name

        $status = "EventID: "+ $item.Name

        Write-Progress -Activity $Activity -Status $status -PercentComplete $pct


        $customobj = "" | select Count,ErrorID,ErrorType,Source,Message

        $customobj.Count = $item.Count

        $customobj.ErrorID = $item.Name


        #get most recent event from the eventID

        $id = $item.Name.ToInt32($Null)


        [System.Threading.Thread]::CurrentThread.CurrentCulture = New-Object "System.Globalization.CultureInfo" "en-US"

        $lastevent = get-winevent -FilterHashtable @{LogName=$eventlog;Id=$id} -MaxEvents 1 -ErrorAction SilentlyContinue


        #depending on local settings, query might fail, if it fails reset to local culture

        if ($lastevent.LevelDisplayName.Length -eq 0)


            [System.Threading.Thread]::CurrentThread.CurrentCulture = $currentCulture

            $lastevent = get-winevent -FilterHashtable @{LogName=$eventlog;Id=$id} -MaxEvents 1



        $customobj.ErrorType = $lastevent.LevelDisplayName

        $customobj.Source = $lastevent.ProviderName

        $customobj.Message = $lastevent.Message


        #prep EventID export

        $exportfile = $resultPath + $eventlog +'_EventID_' + $customobj.ErrorID + ".csv.txt"

        if ($exportEnabled)


            $customobj | Export-Csv $exportfile -NoTypeInformation



        $results += $customobj



    #Latest even details per event

    write-host "Latest event details per event"

    write-host "-----------------------------" 


    #display with format

    $results | Format-Table -AutoSize


    if ($exportEnabled)


        $exportfile = $resultPath + "_lastEvents_short_" + $eventlog + ".txt"

        $results| Format-Table -AutoSize | out-file $exportfile

        $exportfile = $resultPath + "_lastEvents_detail_" + $eventlog + ".txt"

        $results | out-file $exportfile






write-host "Script Completed."



# disable transcripting

if ($enableLogging)

{Stop-Transcript -WarningAction Ignore -ErrorAction SilentlyContinue}




Before you start

  • validate your script execution policy
  • copy the script to a separate folder where you can execute the script
  • validate the script parameters

Script configuration parameters

  • $enableLogging
    • $TRUE = create a transcript of the script during run (does not work in ISE)
    • $FALSE = do not create a verbose log
  • $ExportEnabled
    • $FALSE = do not export the result to file
    • $TRUE = export the results, statistics and event details to file
  • $EventLogList
    • Default: 'System','Application','Setup','Forefront Identity Manager','Forefront Identity Manager Management Agent'
  • $startdate
    • Defines from which point in time the event logs must be analysed
    • HINT: on a system with a large size of event logs, it's advised to limit the history to x days or x weeks. A large volume event log will impact the usage of script memory.


A great thanks to Ed Wilson, the Scripting guy for helping out with troubleshooting on the output and display formats.




Useful resources

The Scripting guy forum: The Official Scripting Guys Forum!

The Script Scripting guy repository on Gallery: here.