When you write software that runs on someone’s machine, it might crash or hang. If this occurs, there are ways to see if this occurred from your program.

For example, I wrote a simple application in C++ called CppTest that crashes by dereferencing a null:

char *ptr = 0;

*ptr = 0;

Lo and behold: my custom application that crashed (not managed code, so it’s not the CLR doing it!) logged an error in the event log! There are actually logs 2 entries created.

The Windows Event Log can be viewed by the Event Viewer (Just type Event at the Start screen)

The event log shows these 2 events for the crash:

1. Source = Application Error at the time of the crash

2. Source = Windows Error Reporting. This could happen much later than the first, and it includes information about whether or not any data was sent to Microsoft about the crash.

clip_image001

The end user has some control over this behavior with the Control Panel:

clip_image003

You can take advantage of these error logs.

For example, you could write some code that looks for the Windows Event Log entries for a crash to improve your code.

Below is a simpel example of code that reads the event log and displays it. You can modify the code to query for your application name. You can find the location of the crash, the faulting module, etc.

Here are the same entries as displayed by the code below:

clip_image004

Start Visual Studio,

File->New->Application->VB->Windows WPF Application

Replace the contents of MainWindow.Xaml.vb with the code below

See also:

Windows Error Reporting and the Appdomain.UnhandledException Event

Windows Error Reporting: Getting Started

http://social.technet.microsoft.com/wiki/contents/articles/3116.event-id-1001-windows-error-reporting.aspx

Set Log Retention Policy

<sample code>


Class MainWindow


    Private Sub MainWindow_Loaded(sender As Object, e As RoutedEventArgs) Handles Me.Loaded
        Me.WindowState = Windows.WindowState.Maximized
        Try
            Dim x = New EventLog("Application")

            Dim entries = x.Entries()
            Dim lst = New List(Of EventLogEntry)

            For i = 0 To entries.Count - 1
                lst.Add(entries(i))
            Next
            Dim q = From log In lst
                    Where "Windows Error Reporting ; Application Error".Contains(log.Source)
                    Where log.Message.ToLower.Contains("cpptest")
                    Order By log.TimeWritten Descending
                    Select
                        EntryType = log.EntryType.ToString,
                        log.Source,
                        log.InstanceId,
                        TimeWritten = log.TimeWritten.ToString(),
                        log.Message
            Dim br = New Browse(q)
            Me.Content = br

        Catch ex As Exception
            Me.Content = ex.ToString
        End Try

    End Sub
End Class

' see http://blogs.msdn.com/calvin_hsia/archive/2007/12/06/6684376.aspx 
Class Browse
    Inherits ListView
    Sub New(ByVal Query As Object, Optional ByVal Parent As Object = Nothing)
        Dim gv As New GridView
        Me.View = gv
        Me.ItemsSource = Query
        If Not Parent Is Nothing Then
            If Parent.GetType.BaseType Is GetType(Window) Then
                CType(Parent, Window).Title = "# items = " + Me.Items.Count.ToString
            End If
        End If
        Me.AddHandler(GridViewColumnHeader.ClickEvent, New RoutedEventHandler(AddressOf HandleHeaderClick))
        If Query.GetType.GetInterface(GetType(IEnumerable(Of )).FullName).GetGenericArguments(0).Name = "XElement" Then ' It's XML 
            Dim Elem1 = CType(Query, IEnumerable(Of XElement))(0).Elements ' Thanks Avner! 
            For Each Item In Elem1
                Dim gvc As New GridViewColumn
                gvc.Header = Item.Name.LocalName
                gv.Columns.Add(gvc)
                Dim bind As New Binding("Element[" + Item.Name.LocalName + "].Value")
                gvc.DisplayMemberBinding = bind
                gvc.Width = 180
            Next
        Else ' it's some anonymous type like "VB$AnonymousType_1`3". Let's use reflection to get the column names 
            For Each mem In From mbr In _
            Query.GetType().GetInterface(GetType(IEnumerable(Of )).FullName) _
            .GetGenericArguments()(0).GetMembers _
            Where mbr.MemberType = Reflection.MemberTypes.Property
                Dim datatype = CType(mem, Reflection.PropertyInfo)
                Dim coltype = datatype.PropertyType.Name
                Select Case coltype
                    Case "Int32", "String", "Int64"
                        Dim gvc As New GridViewColumn
                        gvc.Header = mem.Name
                        gv.Columns.Add(gvc)
                        If coltype <> "String" Then
                            gvc.Width = 80
                            Dim XAMLdt = _
                            <DataTemplate
                                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                                >
                                <StackPanel Orientation="Horizontal">
                                    <TextBlock Name="tb"
                                        Text=<%= "{Binding Path=" + mem.Name + "}" %>
                                        Foreground="Black"
                                        FontWeight="Bold"
                                        Background="SpringGreen">
                                    </TextBlock>
                                </StackPanel>
                            </DataTemplate>
                            gvc.CellTemplate = System.Windows.Markup.XamlReader.Load(XAMLdt.CreateReader)
                        Else
                            gvc.DisplayMemberBinding = New Binding(mem.Name)
                            gvc.Width = 180
                        End If
                End Select
            Next
        End If
        Dim XAMLlbStyle = _
        <Style
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            TargetType="ListBoxItem">
            <Setter Property="Foreground" Value="Blue"/>
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="True">
                    <Setter Property="Foreground" Value="White"/>
                    <Setter Property="Background" Value="Aquamarine"/>
                </Trigger>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Foreground" Value="Red"/>
                </Trigger>
            </Style.Triggers>
        </Style>
        Me.ItemContainerStyle = Windows.Markup.XamlReader.Load(XAMLlbStyle.CreateReader)
    End Sub
    Dim _Lastdir As System.ComponentModel.ListSortDirection = ComponentModel.ListSortDirection.Ascending
    Dim _LastHeaderClicked As GridViewColumnHeader = Nothing
    Sub HandleHeaderClick(ByVal sender As Object, ByVal e As RoutedEventArgs)
        If e.OriginalSource.GetType Is GetType(GridViewColumnHeader) Then
            Dim gvh = CType(e.OriginalSource, GridViewColumnHeader)
            Dim dir As System.ComponentModel.ListSortDirection = ComponentModel.ListSortDirection.Ascending
            If Not gvh Is Nothing AndAlso Not gvh.Column Is Nothing Then
                Dim hdr = gvh.Column.Header
                If gvh Is _LastHeaderClicked Then
                    If _Lastdir = ComponentModel.ListSortDirection.Ascending Then
                        dir = ComponentModel.ListSortDirection.Descending
                    End If
                End If
                Sort(hdr, dir)
                _LastHeaderClicked = gvh
                _Lastdir = dir
            End If
        End If
    End Sub
    Sub Sort(ByVal sortby As String, ByVal dir As System.ComponentModel.ListSortDirection)
        Me.Items.SortDescriptions.Clear()
        Dim sd = New System.ComponentModel.SortDescription(sortby, dir)
        Me.Items.SortDescriptions.Add(sd)
        Me.Items.Refresh()
    End Sub
End Class

</sample code>