Structured Exception Handling in DotNet

18
8/11/2019 Structured Exception Handling in DotNet http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 1/18 Arnaldo Sandoval I began my run in the IT field back in 1975 while at the University getting my Indus Engineer Bachelor Degree; Wang Basic language and Burroughs 6700's FORTRAN COBOL, working as a Teach assistance for a fist full of dollars, since then I had wo in four different countries: Venezuela, USA, Mexico and Australia, the Business Basi Language the main skill expected from me; learning Unix, C, PASCAL, Uniplex, WordPerfect, 20/20 in the la 80s, Sybase in the early 90 Basis BBx in the 90s, Micros VBA in the mid 90s, Visual B version 3.0 around 1996; m to Australia in the lates 90s here I kept learning, Transo Universal Business Languag Oracle, Microsoft SQL Serve Visual Basic .Net; working f major Australian company i building material market. I worked for Computers Manufacturing companies (M Basic Four after reading the Wikepedia definition, it feels good being an active part o industry), and high rollers companies (DOLE, Pepsico w they operated Pizza Hut, KF Taco Bell and PFS, Boral Limited), roaming the world while doing so, exposed to cutting edge technologies o their time, creating it when opportunity required so. I currently look after an Orac data warehouse, sourcing it data from four or five legac applications, servicing Cryst Reports and Cognos Cubes, developed VB and Net solut I could claim the phrase “I been there, done that” suits like a globe, always address any challenge with an engin mind, which is different to a mindset. evCity.NET  - http://www.devcity.net ructured Exception Handling in .NET (ApplicationException) p://www.devcity.net/Articles/284/1/article.aspx Arnaldo Sandoval blished on 11/4/2006 eryone tries to write error free applications, but we all know end users are smarter than us, finding ways to break our well protected applications. The e given the answer "I don't know" when we ask the obvious question "What were you doing?", or "I can't find it" to our inquiry "Did you write down the e ssage?" s article guides you through the .Net Framework features at your disposal to handle applications' errors, also known as Exceptions. Once you unders concepts, the code supplied could be integrated into your existing or new applications, providing comprehensive Exceptions support that will benefit dusers and support team. roduction TRODUCTION eryone tries to write error free applications, but we all know end users are smarter than us, finding ways to break our well protected applications. The e given the answer "I don't know" when we ask the obvious question "What were you doing?", or "I can't find it" to our inquiry "Did you write down the e

Transcript of Structured Exception Handling in DotNet

Page 1: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 1/18

Arnaldo Sandoval

I beganmy runin theIT fieldback in1975whileat the

University getting my IndusEngineer Bachelor Degree; Wang Basic language andBurroughs 6700's FORTRANCOBOL, working as a Teachassistance for a fist full of dollars, since then I had woin four different countries:Venezuela, USA, Mexico andAustralia, the Business BasiLanguage the main skillexpected from me; learning

Unix, C, PASCAL, Uniplex,WordPerfect, 20/20 in the la80s, Sybase in the early 90Basis BBx in the 90s, MicrosVBA in the mid 90s, Visual Bversion 3.0 around 1996; mto Australia in the lates 90shere I kept learning, TransoUniversal Business LanguagOracle, Microsoft SQL ServeVisual Basic .Net; working fmajor Australian company ibuilding material market. I worked for ComputersManufacturing companies (MBasic Four after reading theWikepedia definition, it feelsgood being an active part o

industry), and high rollerscompanies (DOLE, Pepsico wthey operated Pizza Hut, KFTaco Bell and PFS, BoralLimited), roaming the worldwhile doing so, exposed tocutting edge technologies otheir time, creating it when opportunity required so. Icurrently look after an Oracdata warehouse, sourcing itdata from four or five legacapplications, servicing CrystReports and Cognos Cubes,developed VB and Net solutI could claim the phrase “I been there, done that” suitslike a globe, always address

any challenge with an enginmind, which is different to amindset.

evCity.NET - http://www.devcity.net

ructured Exception Handling in .NET (ApplicationException)p://www.devcity.net/Articles/284/1/article.aspxArnaldo Sandovalblished on 11/4/2006

eryone tries to write error free applications, but we all know end users are smarter than us, finding ways to break our well protected applications. Thee given the answer "I don't know" when we ask the obvious question "What were you doing?", or "I can't find it" to our inquiry "Did you write down the essage?"

s article guides you through the .Net Framework features at your disposal to handle applications' errors, also known as Exceptions. Once you unders concepts, the code supplied could be integrated into your existing or new applications, providing comprehensive Exceptions support that will benefit dusers and support team.

roduction

TRODUCTION 

eryone tries to write error free applications, but we all know end users are smarter than us, finding ways to break our well protected applications. Thee given the answer "I don't know" when we ask the obvious question "What were you doing?", or "I can't find it" to our inquiry "Did you write down the e

Page 2: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 2/18

ssage?" 

ssages like the one above may frighten end users. They may think it was their fault, preferring to hide any evidence from us, perhaps thinking "This gking a lot of money and wants me to look after his/her shortcomings".

T FRAMEWORK EXCEPTION HANDLING 

e .Net Framework provides several Exception Handling classes, We implement them here and there, We try our best to trap as many errors as we canurning nice error messages to the user, like the one below:

the .Net Framework classes derive from the SystemException one. It also provides the ApplicationException class as well. It is Microsoft's recomment we implement the ApplicationExceptionss in our applications. This recommendation has triggered several discussions on the Internet with opinions in favour or against its usage. Joining thcussion is pointless, however there are links to some of them in the References section in this thread.

e code posted in this thread implements an Exception Handling class based on the suggested ApplicationException class, with some value added prod method you may find helpful. It is coded in VB.Net 2003 as there are plenty of versions written in C#. It also includes a test project that checks theditional features implemented. 

RUCTURED EXCEPTION HANDLING (SEH) 

Barton Friedland's article .NET Anatomy - Structured Exception Handling in .NET he wrote "structured exception handling (SEH), a service built into tre of .NET and available to all languages supported by it. Since the infrastructure for this service is built-in, there is very little code required to take fullvantage of these features." which is true and fascinating.

e .Net Framework's built-in Exception Services give us so much information about the environment of the process triggering it, plus additional informatposed by the .Net Framework itself, that we should be able to develop a robust Exception Handling "component" that we can use in all our applications

fore getting to the detail of the Exception Handling Component, let's overview what the .Net Framework has to offer on this matter.

Y-CATCH-FINALLY-END TRY  

e all know about the Try-Catch-Finally-End Try error trapping block; it goes like this:

Public Sub MyMethod()'' Code before the Try-End Try block'Try

'' You application code goes here

'Catch se As SystemException

'' Error handling code, or Exception Handling code, basically the same thing.'

Finally'' Common block to perform some cleansing after the exception.'

End Try'' Code after the Try-End Try block'

nd Sub

y error outside the Try-End Tryck will trigger an untrapped exception. If the method (MyMethod) is outside a Try-End Try block itself, the exception will escalate, and if nobody catch

ur application will crash, returning an ugly message like this one:

Page 3: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 3/18

 

owing this, you would try to put you code inside a Try-End Try  block, wouldn't you? Well, there is another discussion on the internet regarding the usagy 

cks, this one focusing on the performance impact of exception trapping in .NET. Once again, Barton Friedland's article has a nice explanation about thceptions are handled in the .NET Framework. A point not documented in these discussions is the overhead that occurs when your application triggers ception.

turning to the example, this time using more meaningful code,

Private Sub Button4_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) _Handles Button4.Click 

Dim a As IntegerDim b As Integer = 5Dim c As Integer = 0 

Try a = b / c

Catch e1 As SEHComponent.ErrorHandlingExceptionShowError(e1)'Catch se As SystemException' MessageBox.Show(se.Message, "System Exception", _' MessageBoxButtons.OK, _' MessageBoxIcon.Error)

End Try 

nd Sub

e Button4's click event will trigger an Arithmetic Exception because there is a division by zero. The exception will go untrapped because the Catch we are upecting an SEHComponent.ErrorHandlingException exception. Implementations like this will crash out with a message like this:

e Exception coded on the first (and unique) catch is not designed to process OverflowExceptions, We can improve the code by removing the commen second catch.

ge 2

rya = b / c

atch e1 As SEHComponent.ErrorHandlingExceptionShowError(e1)

atch se As SystemExceptionMessageBox.Show(se.Message, "System Exception", MessageBoxButtons.OK, _MessageBoxIcon.Error)

nd Try

s time the OverflowException is trapped by the second catch, the SystemException one! This is happening because ALL the exception classes are chthe SystemException class, including the ApplicationException class. For this simple reason, the code shown above will display the following error methe user.

Page 4: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 4/18

 

ooks nice and clean, no end user will be intimidated with a message like this.

OP-UP ERROR MESSAGES SIDE EFFECTS 

popup error message is a nice way to tell our application's user about any unexpected error in the application. They are less frightening than those retthe runtime. Nevertheless, it has its shortcoming if your application is not recording key information about the exception at the time it happens and yo

pecting the user to write the details down on a piece of paper. In this case you should train him/her on what information is meaningful to you, like the

ssage (Arithmetic operation resulted in an overflow), the popup form title (sometimes: System Exception) and the form he/she was working on w exception happens (Form1). Sometimes they do a great job collecting this info for you, but there are risks you don't get the whole picture.

ur application is aware of a lot of things at the time an exception happens. Wouldn't it be nice if you could write that information to a file or database, oail it to you, instead of relying on the end user help. The message shown below is not very user friendly but it illustrates what exception classes could a whole into your applications.

ell, the message above tells us a lot of technical things when the error happened, but as previously said, it is not user friendly. However you can writeormation to a file or database, including the date and time it happened. You could even email it to yourself, or perhaps send an SMS message with allormation.

E ErrorHandlingException CLASS 

the next section of this article we meet the ErrorHandlingException class, a class based on the ApplicationException class. It has the following featur

Collect the date and time of the exception.Identifies the Machine, Operating System, and User.Identifies the application name, application version, culture and method. Accept an Action parameter, where you can pass a more specific explanation of what your application was doing at the time of the exception.It does not hide any existing property or method provided by its parent class: ApplicationException.Write these exception's details to a log file or database (Access).

side the features listed above, you can expand it, implementing new functionalities, like:

Send emails or SMS messages containing the exception details.You can easily write the exception's details to other database (MS SQL, Oracle)Its project and source code is included, so you can enhance it to suit your requirements.

w, we will walk thru the code for the ErrorHandlingException class, explaining its most relevant properties and methods. The project ErrorHandlingExcme name) contains the mentioned class, and it is assigned to the namespace SEHComponent (Structured Exception Handling Component).

Page 5: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 5/18

mports System.Data.OleDbmports System.Configuration.ConfigurationSettings

Page 6: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 6/18

ge 3

e two imported namespaces are required by the methods handling data access and the application configuration file. You should import the namespacS SQL and/or Oracle if you wish to extend this class by implementing either database to store the ExceptionLog data base.

SERIALIZABLE()>Public Class ErrorHandlingException

Inherits System.ApplicationException

e class declaration is preceded by the Serializable token and a couple of methods are required to implement its serialization.

lowing Microsoft recommendation, it inherits the System.ApplicationException class, which enables the class to be used in exception trappingpplicationException trapping). The ApplicationException class exposes the following constructors, methods and properties:

nstructors:

 ApplicationException Constructor () (*) ApplicationException Constructor (String) (*) ApplicationException Constructor (SerializationInfo, StreamingContext) (*) ApplicationException Constructor (String, Exception) (*)

thods:

Object.EqualsException.GetBaseExceptionObject.GetHashCodeException.GetObjectData (*)Object.GetType

Exception.ToString (*)

operties:

Exception.HelpLinkException.InnerExceptionException.MessageException.StackTraceException.TargetSite

ose with an asterisk (*) are the ones this implementation cater for by providing additional code. Beside the class members previously listed, we are alsplementing these ones: 

stom Constructors:

 ApplicationException Constructor (Method Action As String, message As String) ApplicationException Constructor (Method Action As String, message As String, innerException)

thods:

Private Clear()Private GetApplicationAttributes()Public GetExceptions()Public Save(TargetErrorLog, TargetOutput)Private SaveToFile(TargetOutput)Private SaveToAccess(TargetOutput)

operties:

 ApplicationVersion ApplicationCultureErrorDateErrorTimeMachineName

MethodMethodActionOSVersion

riables Declaration Region: s is the first region in our class code. Here all the private and public members required by the class' properties and methods are declared, as shown

Private _ObjectVersion As String = "0.0"Private bVersion As Boolean = False Private _ObjectCulture As String = "Unknown" Private bCulture As Boolean = False Private _MethodAction As String = "Unknown" Private _UserName As String = System.Environment.UserNamePrivate _MachineName As String = System.Environment.MachineNamePrivate _OSVersion As String = System.Environment.OSVersion.ToStringPrivate _ErrorDate As DatePrivate _ErrorTime As TimeSpan

Public Enum TargetErrorLogs

Page 7: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 7/18

FlatFileAccess

End Enum

Const DEFAULT_CONNECTION_STRING As String = "DBConnStringErrorHandlingException"

u may notice that we are using the System.Environment namespace to obtain the user name, machine name and operating system version> Your ception handling requirements could be different and so you may need to use other namespaces to implement additional properties. 

andard Constructors Region: ese are the constructors you may never have to change.

Public Sub New()

MyBase.New()

Me.Clear()

End Sub 

Public Sub New(ByVal message As String)

MyBase.New(message)Me.Clear()

End Sub 

Public Sub New(ByVal message As String, _ByVal innerException As SystemException)

MyBase.New(message, innerException)Me.Clear()

End Sub

ere is nothing fancy in these constructors, perhaps the only one needed more explanation being the reference to the private method Clear() that is explther down this post. 

ge 4

-Serialization Constructor s is the constructor enforced by the Serializable token in front of the Class declaration. It rebuilds all the class private members after a serialization any need to modify this constructors if you add or remove properties from this class.

Public Sub New(ByVal info As System.Runtime.Serialization.SerializationInfo, _ByVal context As System.Runtime.Serialization.StreamingContext)

'MyBase.New(info, context)

_ObjectCulture = info.GetString("ApplicationCulture")_ObjectVersion = info.GetString("ApplicationVersion")bCulture = info.GetBoolean("ApplicationCultureFlag")bVersion = info.GetBoolean("ApplicationVersionFlag")_MethodAction = info.GetString("MethodAction")_MachineName = info.GetString("MachineName")_UserName = info.GetString("UserName")_OSVersion = info.GetString("OSVersion")_ErrorDate = info.GetDateTime("ErrorDate")_ErrorTime = DirectCast(info.GetString("ErrorTime"), TimeSpan)

End Sub

stom Constructors Region: 

stom constructors are an important factor when inheriting from the ApplicationException class. Here is where you implement additional properties to rticular exception handling class and you may add as many as your solution requires.

e are introducing the MethodActionoperty as one of those additional properties this exception class supports. When you throw an exception you can pass a message that explains what yde was trying to do. If your method has to trigger more than one exception, your message should include some kind of description of the action takeinen the error condition was found. That is precisely why the MethodAction

operty came to life. Developers working with this exception class can pass this additional information without messing too much with the exception'sssage.

e next two constructors provide support for the MethodAction property.

Public Sub New(ByVal MethodAction As String, _ByVal message As String)

MyBase.New(message)_MethodAction = MethodAction

End Sub 

Page 8: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 8/18

Public Sub New(ByVal MethodAction As String, _ByVal message As String, _ByVal innerException As SystemException)

MyBase.New(message, innerException)_MethodAction = MethodAction

End Sub

you can see, each one of these constructors takes a MethodAction parameter, which is assigned to the private member _MethodAction. Later on thss exposes its value with the MethodAction

operty. I hope that the chosen names do not confuse you, as a parameter was named MethodAction, and a property goes with the same name.

e first constructor takes just the message parameter for the exception, while the second handles two, the message and the innerException. This is ndard practice when implementing additional parameters into exception classes.

operties Region: w is time to show the region where the properties' declaration takes place in this class. The first thing to notice is that all these properties are Readonn't want any developer working with your exception class to tamper with the exception attributes.

e already explained that the machine name, operating system version and user name properties come from the System.Environment name space. Wout the remaining properties, how are they coming to life? Well, the private method GetApplicationAttributes() takes care of them.

Public ReadOnly Property ApplicationVersion() As String Get 

If bVersion = False Then GetApplicationAttributes() 

End IfReturn _ObjectVersion

End Get

End Property

Public ReadOnly Property ApplicationCulture() As StringGet

If bCulture = False Then GetApplicationAttributes()

End IfReturn _ObjectCulture

End GetEnd Property

Public ReadOnly Property ErrorDate() As StringGet

Return _ErrorDate.ToString("yyyy/MM/dd")End Get

End Property

Public ReadOnly Property ErrorTime() As StringGetReturn _ErrorTime.Hours.ToString & ":" & _ErrorTime.Minutes.ToString

End GetEnd Property

Public ReadOnly Property MachineName() As StringGet

Return _MachineNameEnd Get

End Property

Public ReadOnly Property Method() As StringGet

Return MyBase.TargetSite.NameEnd Get

End Property

Public ReadOnly Property MethodAction() As StringGet

Return _MethodActionEnd Get

End Property

Public ReadOnly Property OSVersion() As StringGet

Return _OSVersionEnd Get

End Property

Public Overrides Function ToString() As String

Return MyBase.ToString & vbCrLf & _"Source Object : " & Me.Source & vbCrLf & _"Source Method : " & Me.TargetSite.Name & vbCrLf & _

"Method Action : " & _MethodAction

Page 9: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 9/18

End Function

Public ReadOnly Property UserName() As StringGet

Return _UserNameEnd Get

End Property

ke a look at the ToStringction. Yes, it is listed as a property, but readonly properties and functions are closely related. A function behaves like a Readonly property and vice e first thing to notice is: It is incomplete, there are properties missing, you can add them later, We didn't because we were implementing additional

ctionalities to the class, but the idea with the ToString function is that it should return all the class private members.

ge 5

e Methods region: e class implements seven methods. We will go through them now.

vate Clear method: 

Private Sub Clear()

_ObjectVersion = "0.0"_ObjectCulture = "Unknown" _MethodAction = "Unknown" _UserName = System.Environment.UserName_MachineName = System.Environment.MachineName_OSVersion = System.Environment.OSVersion.ToStringbVersion = False bCulture = False 

GetApplicationAttributes()

End Sub

e Clear method is Private because you don't want developers working with your class to wipe out the exception attributes. The method is referenced bnstructors at the time they are initializing the class. If you add new Private members to the class you should also initialize them here. You may think thiear method is redundant because private member are already initialized when you declare them. However including their initialization here will make d future developers taking over the responsibility of maintaining this code should understand it easier.

ere is a reference to the mystery method GetApplicationAttributes(), we will get to it very shortly.

e GetObjectData Method: s method is the one de-serializing this class. Due to its function it is a very important one. If you are not careful coding it, the class may have seriali

oblems. The main goal when de-serializing and serializing objects is their private members values do not change or get lost. In other words, its stateould not change.

Public Overrides Sub GetObjectData(ByVal info As System.Runtime.Serialization.SerializationInfo, _ByVal context As System.Runtime.Serialization.StreamingContext)

MyBase.GetObjectData(info, context)

info.AddValue("ApplicationCulture", _ObjectCulture)info.AddValue("ApplicationVersion", _ObjectVersion)info.AddValue("ApplicationCultureFlag", bCulture)info.AddValue("ApplicationVersionFlag", bVersion)info.AddValue("MethodAction", _MethodAction)info.AddValue("MachineName", _MachineName)info.AddValue("UserName", _UserName)info.AddValue("OSVersion", _OSVersion)info.AddValue("ErrorDate", _ErrorDate)info.AddValue("ErrorTime", _ErrorTime)

End Sub

e method is public and overrides the base class GetObjectData method, and then it de-serializes the base class with this line of code

MyBase.GetObjectData(info, context)

e info object contains the de-serialized base class. Now you should add all your new private members to the info object and you will be done.

ou are expanding this class by adding new properties, you should include their private member in this method as well.

vate method GetApplicationAttributes: ou are familiar with the Gang of Four (GoF) design patterns, you may think this class implements a Facade Design Pattern for the application excepss. The GoF quote below is taken from their literature.

GoF Intent for Facade: Provide a unified interface to a set of interfaces in a subsystem. The Facade defines a higher-level interfacat makes the subsystem easier to use.

Page 10: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 10/18

e GetApplicationAttributes method enforces this approach; it drills deep into the exception objects trees, finding attributes later exposed as properties ss.

Private Sub GetApplicationAttributes()

If Not Me.TargetSite Is Nothing ThenIf Not Me.TargetSite.ReflectedType Is Nothing Then 

If Not Me.TargetSite.ReflectedType.AssemblyQualifiedName Is Nothing Then

Dim s() As String = Split(Me.TargetSite.ReflectedType.AssemblyQualifiedName)Dim s1 As String 

For Each s1 In sIf bVersion = False Then

If s1.IndexOf("Version", 0) >= 0 Then Dim s2() As String = Split(s1, "=")_ObjectVersion = s2(1)If _ObjectVersion.IndexOf(",") >= 0 Then 

_ObjectVersion = _ObjectVersion.Substring(0, _ObjectVersion.IndexOf(","))End IfbVersion = True 

End IfEnd IfIf bCulture = False Then

If s1.IndexOf("Culture", 0) >= 0 ThenDim s2() As String = Split(s1, "=")_ObjectCulture = s2(1)If _ObjectCulture.IndexOf(",") >= 0 Then 

_ObjectCulture = _ObjectCulture.Substring(0, _ObjectCulture.IndexOf(","))End If

bCulture = TrueEnd If

End IfIf bVersion = True And bCulture = True Then

Exit ForEnd If

NextEnd If

End IfEnd If

_ErrorDate = Now.Date_ErrorTime = Now.TimeOfDay

End Sub

e method is working with the AssemblyQualifiedName property found at the ReflectedType member, which is located inside the exception's TargetSi

Is Nothing validations are required by the way exception objects behave - more on that later on, in the post explaining How to use thisrorHandlingException class.

e AssemblyQualifiedNameoperty contains the executable's version number and its culture. Finding and exposing them will make developers' life working with this class easier.

he implementation approach used to build this class is clear to you, you may want to use this method to find and expose additional information about thception being handled.

e Public Save() method: w that this ApplicationExecption class collects a lot of information about the exception being handled, the Save() method allows developers implement"save" the exception details to an error log object. The class already implements two of these error log objects; a flat text file or an Access Database; yn extend this class to implement "additional" error log objects.

Public Sub Save(ByVal TargetErrorLog As TargetErrorLogs, _ByVal TargetOutput As String)

'' Save exception details to log table in ApplicationException database'If bVersion = False OrElse bCulture = False Then 

GetApplicationAttributes()End If

Select Case TargetErrorLogCase TargetErrorLogs.FlatFile

SaveToFile(TargetOutput)

Case TargetErrorLogs.AccessSaveToAccess(TargetOutput)

End Select

End Sub

akes two parameters: 

Page 11: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 11/18

rgetErrorLog: This is of a TargetErrorLogs type, telling the method the procedure to follow to "save" the exception details. The type was declared at the to class:

Public Enum TargetErrorLogsFlatFileAccess

End Enum

rrently defining two values: FlatFile and Access. Developers working with the class can only chose two target error log objects as defined by thisumeration.

ou want to extend this class to "save" the exception details to a new error log object, then you should modify this enumeration adding its associatedy-word name.

rgetOutput:he target error log object is a flat file you should pass its name thru this parameter. If the target is a database, then the connection string "key" as def application config file should be passed instead. If you extend this class to email the exception details then this parameter is likely to receive a distribof the emails recipients for the email. The logic within the Save() and its associated "SaveTo ..." methods deals with an empty TargetOutput value.

e next thing the Save method does is check for the application version and culture. If they are unknown the GetApplicationAttributes() is invoked, mre the class state is up to date.

ally, the Save method sorts out the target error log object to use based on the TargetErrorLog parameter received.

s time we are using a sort of GoF Factory Design Pattern. Each target error log object has a private "SaveTo ... " method, because you don't wantvelopers working with this class to implement different "SaveTo ..." methods thru the application. Besides, sticking with the Save() factory method willot easier to switch from writing to a database error log into emailing the exceptions details. An entry in the application config file will do so without

compiling your application.

ge 6

vate SaveToFile() method: s is the method writing the exception details to a flat file that developers provide when calling the Save() method or to the default file coded in the clas

Private Sub SaveToFile(ByVal TargetFile As String)

If TargetFile.Length = 0 Then TargetFile = "C:\Temp\ApplicationErrors.log" 

ElseIf TargetFile.IndexOf(":\") < 0 Then 

TargetFile = "C:\Temp\" & TargetFileEnd If

End If

Dim OutputFile As New System.IO.StreamWriter(TargetFile, True)Dim sOutput As String 

sOutput = Me.ErrorDate & "/" sOutput &= Me.ErrorTime & "/" sOutput &= Me.MachineName & "/" sOutput &= Me.OSVersion & "/" sOutput &= Me.UserName & "/" sOutput &= Me.Source & "/" sOutput &= Me.ApplicationVersion & "/" sOutput &= Me.ApplicationCulture & "/" sOutput &= Me.Method & "/" sOutput &= Me.MethodAction & "/" sOutput &= Me.Message & "/" sOutput &= Me.StackTrace.Trim

OutputFile.WriteLine(sOutput)OutputFile.Close()

rgetFile: This parameter contains the name and location of the file where the exception details will be written.

e first thing the method does is making sure a file name is provided, if the parameter is empty, it assigns the default target flat file:Temp\ApplicationErrors.log , otherwise, it checks the given file name for a drive name sign within the name, searching for ":\" does the trick, if no eviderive name is found, the code insert the folder "C:\Temp\".

ARNING: This approach has its weakness, and you may want to improve it.

The log file could be at each user workstation's C:\Temp folder.1.

Users' workstations C: drive could be hidden.2.

The drive validation seems poorly implemented, what about a network drive name?3.

e method keep going by opening the TargetFile, building a long string with all the exception details, separating them with pipes, appending the long str file and finally closing the TargetFile.

vate SaveToAccess() Method: s method write our application's exception details to an Access Database, the access database is accessed thru a connection string, so as long as it i

Page 12: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 12/18

achable we have nothing to worry about.

Private Sub SaveToAccess(ByVal ConnectionStringKey As String)

Dim SQL_Connection As New OleDbConnectionDim SQL_Command As New OleDbCommandDim sSQL_Command As String = "" '' Retrieve the connection string, from config file, pass it to the command object' If ConnectionStringKey.Length = 0 Then 

ConnectionStringKey = DEFAULT_CONNECTION_STRINGEnd If 

SQL_Connection.ConnectionString = AppSettings.Get(ConnectionStringKey)SQL_Command.Connection = SQL_Connection'' Build the INSERT command'sSQL_Command = "INSERT INTO ErrorLog ( " & _

" [ErrorDate] " & _" , [ErrorTime] " & _" , [Machine] " & _" , [OSVersion] " & _" , [User] " & _" , [Application] " & _" , [Version] " & _" , [Method] " & _" , [Action] " & _" , [Message] " & _" , [ErrorStack] " & _") " & _"VALUES ( " & _

" @ErrorDate " & _" , @ErrorTime " & _" , @Machine " & _" , @OSVersion " & _" , @User " & _" , @Application " & _" , @Version " & _" , @Method " & _" , @Action " & _" , @Message " & _" , @ErrorStack " & _")" 

'' We don't have to worry about apostrophes in the fields we are saving to the database' because we are passing their values as parameters, and its add method takes care of them.'With SQL_Command

.Parameters.Add("@ErrorDate", Me.ErrorDate)

.Parameters.Add("@ErrorTime", Me.ErrorTime)

.Parameters.Add("@Machine", Me.MachineName)

.Parameters.Add("@OSVersion", Me.OSVersion)

.Parameters.Add("@User", Me.UserName)

.Parameters.Add("@Application", Me.Source)

.Parameters.Add("@Version", Me.ApplicationVersion)

.Parameters.Add("@Method", Me.Method)

.Parameters.Add("@Action", Me.MethodAction)

.Parameters.Add("@Message", Me.Message)

.Parameters.Add("@ErrorStack", Me.StackTrace.Trim)

.CommandText = sSQL_CommandEnd With '' We are now ready to go'

Try 'SQL_Connection.Open()SQL_Command.ExecuteNonQuery()

Catch ex As OleDbException'' We got an error!!! saving the exception to file instead.'SaveToFile("")'

End Try'' Cleaning up'SQL_Command.Dispose()SQL_Connection.Close()SQL_Connection.Dispose()

'End Sub 

Page 13: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 13/18

nnectionStringKey:s parameter pass the connection string "key" as defined at the application's config file, for the database we are using. The sample application attached

est_ErrorHandlingException) defined it as shown:

appSettings><!-- User application and configured property settings go here.--><!-- Example: <add key="settingName" value="settingValue"/> --> <add key="DBConnStringErrorHandlingException" value="Provider=Microsoft.Jet.OLEDB.4.0;Data

ource=C:\Temp\TargetErrorLog.mdb" />

/appSettings>

cause, it is a connection string, you should replace it with the appropriated entry for your database location; the connection string key name is:BConnStringErrorHandlingException, and the class uses it as a default when an empty connection string key is passed.

e connection string uses the access database TargetErrorLog.mdb

ated at the C:\temp folder, the database name could be anything, and there are no restrictions, the same goes with the folder C:\temp.

we are retrieving the connection string from the application's config file, we should include the namespace: Importsstem.Configuration.ConfigurationSettings at the top of the class file, as previously explained.

ARNING: Keep in mind the SaveToAccessthod lacks an strong validation for a missing connection string, you should make sure the application's config file has its entry before playing around wss. 

ge 7

w that most of the disclaimers and explanations for the connection string are covered, let's move on with the method's remaining logic. It is nothing buin vanilla INSERT INTO method. It is expecting the table ErrorLog.  This table is defined with the following columns: 

ere is a column per each member of the Exception class we want to save into the error log. If you want to implement a different data base like MS SQL

acle, you should create a table named ErrorLog with the same columns, although Oracle is a little bit tricky handling the Auto Increment column.

the columns from the ErrorLogle are surrounded with brackets to avoid reserved words exceptions. We are using parameters to assign values to each of the table's columns; it is say as we don't have to worry about apostrophes in the data.

e method relies on the OleDB namespace, so we are importing it at the top of the class file, as previously explained.

P:ou expand this class to support MS SQL or Oracle, you should import the appropiate namespaces. The INSERT INTO command is basically the samcess and MS SQL, but with Oracle you should replace the '@' charater with ":" (colons) as that is Oracle's preferred parameters leading character.

blic GetExceptions() Method: s method returns a data table that you can bind to a data grid, providing an easy way to look at all the exceptions written to the ErrorLog table.

Public Function GetExceptions(ByVal ConnectionStringKey As String) As DataTable

Dim SQL_Connection As New OleDbConnectionDim SQL_Command As New OleDbCommandDim sSQL_Command As String = "" Dim SQL_Adapter As New OleDbDataAdapterDim dt As New DataTable '' Retrieve the connection string, from config file, pass it to the command object'If ConnectionStringKey.Length = 0 Then 

ConnectionStringKey = DEFAULT_CONNECTION_STRINGEnd If 

SQL_Connection.ConnectionString = AppSettings.Get(ConnectionStringKey)SQL_Command.Connection = SQL_Connection

sSQL_Command = "SELECT * FROM ErrorLog" SQL_Command.CommandText = sSQL_Command

Try

Page 14: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 14/18

SQL_Adapter.SelectCommand = SQL_CommandSQL_Adapter.Fill(dt)GetExceptions = dt

Catch exc As OleDbExceptionGetExceptions = Nothing 

End Try 

dt.Dispose()SQL_Adapter.Dispose()SQL_Command.Dispose()

SQL_Connection.Close()SQL_Connection.Dispose()SQL_Connection = Nothing SQL_Adapter = Nothing 

End Function

nnectionStringKey: This parameter has the same scope as the one used at the SaveToAccess method, all the disclaimers and explanations written

s method is good to obtain all the exception details from an Access database, small changes are required when dealing with MS SQL and Oracle.

FERENCES: 

plicationException Class by MSDN.plicationException Members by MSDN.ET Anatomy - Structured Exception Handling in .NET by Barton Friedland.ception classes in .NET Framework ceptions by Terry Smith.e Well-Tempered Exception by Eric Gunnerson at Microsoft Corporation

w to write custom exception classes in C# 

SCLAIMER  e code is posted and attached as is, feel free to use it, we advise that you should get acquainted with it before implementing this class in your applicat

main weakness is with the WriteToFile method; you should review and perhaps enhance it, driven by your organization system security rules.

e SaveToAccess() method does not have exception trapping and connection string key validations. You may add this validation or go ahead knowing slim chance it may break at those two danger points.

TACHED PROJECT 

e attached zip file contains the class project ErrorHandlingExceptions. Its Data folder contains the access data base the test project uses to write thceptions details. You should either copy this Access database to your C:\Temp folder, or amend the connection string making it to point to the folder oeference.

e project is written in VB.Net 2003. 

ing ErrorHandlingException Class (i)

OW TO USE THE ErrorHandlingException CLASS: 

s topic explains with a test project (attached) how to use the ErrorHandlingException class described within this thread.

FERENCE TO THE ErrorHandlingException CLASS: e first thing you should do before using the ErrorHandlingExceptionss described above is adding a reference of its DLL to the project where you want to use it.  

Expand your project's tree in the solution explorer.1.Right click the References node.2.

Page 15: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 15/18

Click on the Add Reference option.3.

Click the Browse button.4.

Navigate to the folder where the file ErrorHandlingException.dll is located.5.

Select the file.6.

Click the Open button.7.

Click the Ok button.8.

set, you will be able to use the ErrorHandlingException class through your project's code.

QUIRED CONNECTION STRING AT YOUR PROJECT app.config: ou want to record your application's exceptions to an ErrorLog table as described in the post explaining the Class, its config file should have an entry le.

?xml version=<?xml version="1.0" encoding="utf-8"?>CONFIGURATION>

<APPSETTINGS>

<ADD class=s color="#ff00ff" key="" font DBConnStringErrorHandlingException?<>alue="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Temp\TargetErrorLog.mdb" /></APPSETTINGS>

/CONFIGURATION></APPSETTINGS>

here the key value should be DBConnStringErrorHandlingExceptionich is the default expected entry, or the one of your preference, while the value should point to the location of the Access database you will be using tour Exceptions log.

similar approach of creating a config entry is suggested when you expand the class to save your exception to a database other than access.

Error Resume Next EQUIVALENT USING TRY-END TRY BLOCKS:  e Try-End Try  equivalent of the On Error Resume Next statement is achieved by implementing an empty CATCH  block, as shown:

im a As Integer im b As Integer = 5im c As Integer = 0

rya = b / c

atch ex As Exception

nd Try 

more code

e above sample code illustrates the use of a Try-Catch-End Try  block emulating the On Error Resume Next statement; the error inside the Try  block wp the method execution.

ROWING DATA DRIVEN EXCEPTION: u application is expected to throw an ErrorHandlingExceptionen it finds an error condition with the data your application is handling. It should do something like this:

TryDim a As Integer Dim b As Integer = 5Dim c As Integer = 0'If c <> 0 Then

a = b / cElse

Throw New SEHComponent.ErrorHandlingException( _"Doing some calculations", _"Invalid parameter")

End IfCatch ehe As SEHComponent.ErrorHandlingException

ehe.Save(SEHComponent.ErrorHandlingException.TargetErrorLogs.Access, "")End Try

e example code shows that the application identifies a data error condition, throwing the ErrorHandlingException. The Try block catch it with the varia

e and Saves its details to the target access database without showing any warning message to the user.

will be up to the application logic to determine what to do when the error condition is found after catching the thrown exception.

ANDLING SYSTEM EXCEPTIONS: 

r ErrorHandlingExceptionss is cool to trap any exception thrown by the application upon performing data validation, but it will completely miss any system generated exception.mple code below illustrates the latter fact:  

Try'' Validating data errors and throwing an ErrorHandlingException'

If c <> 0 Then a = b / c

Page 16: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 16/18

Else Throw New SEHComponent.ErrorHandlingException("Division", _

"Trying to divide by zero")End If '' Trapping exceptions, other than ErrorHandlingException' and re-routing it thru its class'a = b / (d * c) '  <==== '

atch ehe As SEHComponent.ErrorHandlingExceptionehe.Save(SEHComponent.ErrorHandlingException.TargetErrorLogs.Access, "")

atch se As SystemExceptionMessageBox.Show(se.Message, _

"System Exception", _MessageBoxButtons.OK, _MessageBoxIcon.Error)

nd Try

e exception thrown by this code: a = b / (d * c)  will be trapped by the SystemException instead. This is true for any Exception your code may throw.

hat you should do to get these excections handled by the ErrorHandlingException is redirect the System Exceptions, as shown.

Try'' try block'a = b / (d * c) '  <==== '

atch se As SystemExceptionTry

Throw New SEHComponent.ErrorHandlingException("Re-routing it", _

se.Message, _se)

Catch ehe As SEHComponent.ErrorHandlingExceptionShowError(ehe)

End Trynd Try

ing the ErrorHandlingException Class (ii)

s time the SystemException Catch block is throwing an Application Exception using our class and passing the System Exception message se.Messag

exception itself as inner exception se to the ErrorHandlingException class By doing this, we can trap the application exception using the Catch ehe AEHComponent.ErrorHandlingException code.

e method ShownError()part of the demo project. You can check it out by downloading the attached project to this article. It basically display a pop-up window describing theception.

mports SEHComponent e code snippets shown so far feature reference to the ErrorHandlingException class by fully qualifying its namespace, but you can avoid too much typiporting its name space with this line of code at the top of the project using it:

mports SEHComponent

ce this is done, the throw and catch statements referencing it become: 

hrow New ErrorHandlingException("Division", _"Trying to divide by zero")

nd / or

atch ehe As ErrorHandlingException

QUIRIES TO THE EXECEPTION LOG 

e ErrorHandlingException class as explained on the first and second pages of this article expose a GetExceptions() method returning a DataTable obu can use this method to provide a quick way to view all the exceptions your application is throwing by adding a data grid to a Windows form or Web Pthe class does not have a presentation layer, you can use it on either Windows or Web applications.

e image below illustrates the enquiry we are talking about.

Page 17: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 17/18

 

e image identifies the application as Test_ErrorHandling t because posting that project into this article was not possible we renamed the application to TestEHE.

e behind the View Exceptions button shown in the picture follows:

im SEH As New ErrorHandlingExceptionim dt As DataTable

t = SEH.GetExceptions("")

f Not dt Is Nothing Then 

dgExceptions.DataSource = dtdgExceptions.ReadOnly = True 

nd If

e GetExceptionsthod accepts a single parameter, the connection string for the database we are using to Save our exceptions errors. As we are passing an empty str class will use the default connection string key, and retrieve the connection string defined at the Application Config file as documented above.

RJECT TestEHE 

e project used to test the ErrorHandlingExceptionss is attached to this post. You can download it to get a better understanding on how to use the class and get familiar with its behavior.

Plain Untrapped Exception and Plain Untrapped Exception (Using Imports) buttons do not display any pop-up message, they just save the excepthe Access database.

u should copy the Access database TargetErrorLog.mdb located at its Data folder to the C:\Temp folder once you unzip the project, or fix the Applicanfig file to point to its location on your PC.

e project has a reference to the ErrorHandlingException.dllary. This reference might be broken once you unzip the projects posted on this thread and you should fix the reference before trying to use it.

ONCLUSIONS

You can extend the ApplicationException class provided by the .Net Framework, implementing additional functionalities that certainly will benefit yoapplication.You can use any .Net development language to implement your ApplicationException class, either C# or VB.Net without major concerns, as you cayour customized exception handling object in any project regardless of the language of preference at your organization.

You may extend the System Exception class, but it is Microsoft remendation that any extention to Exception classes, be done off the ApplicationException class.

Page 18: Structured Exception Handling in DotNet

8/11/2019 Structured Exception Handling in DotNet

http://slidepdf.com/reader/full/structured-exception-handling-in-dotnet 18/18