Article Options
Premium Sponsor
Premium Sponsor

 »  Home  »  .NET Framework  »  Exception Handling in Enterprise Applications  »  Suggestions 5-7
 »  Home  »  .NET Newbie  »  Exception Handling in Enterprise Applications  »  Suggestions 5-7
Exception Handling in Enterprise Applications
by Scott Rutherford | Published  02/28/2005 | .NET Framework .NET Newbie | Rating:
Suggestions 5-7

5. Centralize the handling of errors, but make use of all contextual information.

Putting all of the above practices together gives you a richer context in which to report errors. The actual logic of reporting the error is something that you can implement in a centralized way. In this code example, a critical exception is caught. It is then passed to the central method called HandleError() to be read and logged. HandleError() subsequently calls LogEvent(), which is discussed in #6, below.

[Visual Basic]       
        Try
            Dim sPath As String = "\\MYSERVER\myshare\myfile.txt"
            System.IO.File.Delete(sPath)
        Catch ex As System.IO.FileNotFoundException
            HandleError(ex, EventImportance.Critical, EventID.FILE_ACCESS_ERROR, _
                              "[Delete failed: can't access path.]")
        End Try
    Public Sub HandleError(ByRef e As Exception, ByVal Importance As EventImportance, _
                                                          ByVal ID As EventID, ByVal ExtraInfo As String)
        Dim sMessage As String
        While Not e.InnerException Is Nothing
            e = e.InnerException
            sMessage += Chr(13) + e.Message + " [" + e.GetType().ToString() + "]"
        End While
        If ExtraInfo <> "" Then
            sMessage += Chr(13) + ExtraInfo
        End If
        LogEvent(sMessage, Importance, ID)
    End Sub 

6. Report application errors to the Windows Event Logs

The Windows Event Logs provide an existing infrastructure that can be leveraged in the task of Enterprise error handling. It provides the same reliable error logging as used by the OS, and additionally offers sorting, filtering, and growth control of logs.

[Visual Basic]
    Private Sub LogEvent(ByVal Msg As String, ByVal Type As EventImportance, ByVal ID As Integer)
        Dim sEventLogName = "Application"
        Dim elog As New System.Diagnostics.EventLog(sEventLogName)
        elog.Source = GetAssemblyName()
        If AlreadyLogged(elog, ID, Msg) Then Exit Sub
        Dim EventType As System.Diagnostics.EventLogEntryType
        Select Case Type
            Case EventImportance.Critical
                EventType = System.Diagnostics.EventLogEntryType.Error
            Case EventImportance.Information
                EventType = System.Diagnostics.EventLogEntryType.Information
            Case EventImportance.Warning
                EventType = System.Diagnostics.EventLogEntryType.Warning
        End Select
        Try
            elog.WriteEntry(Msg, EventType, ID)
        Catch ex As System.ComponentModel.Win32Exception
            WriteFile("Windows Event Log [" + sEventLogName + "] is full!  " + GetAssemblyName() _
                    + " application failed to write error " + ID.ToString + ": " + Msg)
        Catch ex As Exception
            WriteFile("Unknown error writing to Windows Event Log [" + sEventLogName + "]!" + _
                    ex.Message + GetAssemblyName() + _
                    " application failed to write error " + ID.ToString + ": " + Msg)
        End Try
    End Sub
    Private Function GetAssemblyName() As String
        Dim assemb As Reflection.Assembly = Reflection.Assembly.GetExecutingAssembly()
        Dim attr As System.Attribute
        For Each attr In assemb.GetCustomAttributes(False)
            If TypeOf attr Is System.Reflection.AssemblyTitleAttribute Then
                GetAssemblyName = CType(attr, System.Reflection.AssemblyTitleAttribute).Title
            End If
        Next
    End Function
    Private Function AlreadyLogged(ByRef Log As System.Diagnostics.EventLog, _
                                   ByVal ID As Integer, ByVal Message As String) As Boolean
        Dim entr As System.Diagnostics.EventLogEntry
        AlreadyLogged = False
        For Each entr In Log.Entries
            If entr.EventID = ID And entr.Message = Message Then
                AlreadyLogged = True
                Exit Function
            End If
        Next
    End Function 

7. Ensure all apps are able to report to the Windows Event Logs

With Windows 2003, security on the Event Logs has changed. You can now define custom Security Descriptors for each log. For example, the following registry key value defines access to the Application Event Log:

HKLM\SYSTEM\CurrentControlSet\Services\EventLog\Applicaton\CustomSD
You need to configure carefully the various event logs used by your program so that it can log properly to the Event Log in all instances, and under the security context of any potential user. You also need to ensure all users have access to read the above registry key or you won’t get far.
    At the end of this value are tokens such as:
  • (A;;0x1;;;DU) - allow domain users to read this event log
  • (D;;0x7;;;BG) - deny built-in guest users (e.g. IUSER, ASPNET user) read, write, and clear
  • (A;;0x3;;;IU) - allow interactive users to read and write to it
    The middle unit of each token is a bitwise AND, in hex format, of 1:read, 2:write, 4:clear.

    Other possible values for the last unit of each token include:
  • BA (Built-in admin)
  • SY (System)
  • AN (Anonymous)
  • SO (Server operators)
  • SU (Service users)
  • any SID representing a specific user or group on the machine or domain.

Comments    Submit Comment

Comment #1  (Posted by an unknown user on 03/08/2005)
Rating
I have yet to put some time in practicing this and the content looks good for producing custom errors. I would like to see your ideas on how to deal with SQL/ODBC type errors in addition to these.
 
Comment #2  (Posted by (The Author) on 03/22/2005)
Rating
For ODBC errors, I catch these in the calling application and report as any other error described in the article. For SQL exceptions, I catch them inside the Stored Proc, and report a meaningful error back to the calling app.
 
Comment #3  (Posted by an unknown user on 08/24/2005)
Rating
Your article is basically focused on logging the event. You should take a look at log4net http://logging.apache.org/log4net/ as a tool it provides both logging level and application code context. It has a multitue of logging connectors (including Event Log.) that can be used simultaneously to log messages within your applications.
 
Comment #4  (Posted by Pawel Pabich on 08/25/2005)
Rating
Hajo,
I do not aggre that usage of enums is good practice.
You should rather create separate class for every type of error.

Pawel
 
Comment #5  (Posted by Piers Lawson on 08/25/2005)
Rating
As mentioned by another contributor, there are frameworks to help with this, such as log4net. An alternative that provides logging and exception handling is the Enterprise Library (EL) available for free from Microsoft. See msdn.microsoft.com/library/en-us/dnpag2/html/entlib.asp

Both these frameworks allow centralised logging to be configured both in terms of destination and levels. The EL also provides other well integrated features such as exception handling, data access, caching, configuration file handling.

I wrote an article introducing the Enterprise Library's logging features here: http://www.codeproject.com/dotnet/GetLoggingWithEntLib.asp
 
Comment #6  (Posted by Jparlato on 08/25/2005)
Rating
Thanks for putting this together. We can obviously choose variations for logging and other aspects, but this was useful - as is.

 
Comment #7  (Posted by Oli on 12/12/2005)
Rating
Great. Thanks....
 
Comment #8  (Posted by an unknown user on 08/09/2006)
Rating
Skimmed over the very basics without going into any detail. Good for juniors i suppose.
 
Sponsored Links