Error Handling Suggestions

  • Thread starter Thread starter jcrouse
  • Start date Start date
J

jcrouse

I am using the following code to trap errors in a sub routine:

Try
Executable code
Catch ex As Exception
Dim strInputE As String = Application.StartupPath & "\Error.txt"
Dim srE As StreamWriter = File.AppendText(strInputE)
srE.WriteLine(vbCr)
srE.WriteLine(vbCr)
srE.WriteLine(DateTime.Now)
srE.WriteLine("------------------")
srE.WriteLine(ex.ToString)
srE.Close()
MsgBox("An Error has occurred. Please check the file " &
Application.StartupPath & "\Error.txt for details.", MsgBoxStyle.Critical,
CPViewer")
Exit Sub
Finally
cleanup code
End Try

I tested this and it seems to work. However, I don't really want to place it
in probably 300 subs in 12 different forms. What are my options here?

Thank you,
John
 
John,
I normally use a global exception handler for logging and display to the
user. I use try/finally more then I use try/catch. I only use try/catch when
there is something specific that I need to do with the exception, otherwise
I let my global exception handlers handle the exception.

Depending on the type of application you are creating, .NET has three
different global exception handlers.

For ASP.NET look at:
System.Web.HttpApplication.Error event
Normally placed in your Global.asax file.

For console applications look at:
System.AppDomain.UnhandledException event
Use AddHandler in your Sub Main.

For Windows Forms look at:
System.Windows.Forms.Application.ThreadException event
Use AddHandler in your Sub Main.

It can be beneficial to combine the above global handlers in your app, as
well as wrap your Sub Main in a try catch itself.

There is an article in the June 2004 MSDN Magazine that shows how to
implement the global exception handling in .NET that explains why & when you
use multiple of the above handlers...

http://msdn.microsoft.com/msdnmag/issues/04/06/NET/default.aspx

For example: In my Windows Forms apps I would have a handler attached to the
Application.ThreadException event, plus a Try/Catch in my Main. The
Try/Catch in Main only catches exceptions if the constructor of the MainForm
raises an exception, the Application.ThreadException handler will catch all
uncaught exceptions from any form/control event handlers.


Something Like:
Try
Executable code
Finally
cleanup code
End Try


Private Shared Sub Application_ThreadException(ByVal sender As Object,
ByVal e As System.Threading.ThreadExceptionEventArgs)

Dim ex As Exception = e.Exception
Dim strInputE As String = Application.StartupPath & "\Error.txt"
Dim srE As StreamWriter = File.AppendText(strInputE)
srE.WriteLine(vbCr)
srE.WriteLine(vbCr)
srE.WriteLine(DateTime.Now)
srE.WriteLine("------------------")
srE.WriteLine(ex.ToString)
srE.Close()
MsgBox("An Error has occurred. Please check the file " &
Application.StartupPath & "\Error.txt for details.", MsgBoxStyle.Critical,
CPViewer")

End Sub

Public Shared Sub Main()
AddHandler Application.ThreadException, AddressOf
Application_ThreadException
Application.EnableVisualStyles()
Application.DoEvents()
Application.Run(New MainForm)
End Sub


Hope this helps
Jay
 
Well, the simplest way would be to write a common error handling routine
which you can then be called from various subs in various forms - ofcourse,
assuming that the error handling is identical for all of these procedures.
Probably something like:

Friend Sub MyErrorHandler(ex as Exception)
Dim strInputE As String = Application.StartupPath & "\Error.txt"
Dim srE As StreamWriter = File.AppendText(strInputE)
srE.WriteLine(vbCr)
srE.WriteLine(vbCr)
srE.WriteLine(DateTime.Now)
srE.WriteLine("------------------")
srE.WriteLine(ex.ToString)
srE.Close()
MsgBox("An Error has occurred. Please check the file " &
Application.StartupPath & "\Error.txt for details.",
MsgBoxStyle.Critical,
CPViewer")
End

and then call this sub as:

Try
' executable Code
Catch ex As Exception
MyErrorHandler(ex)
Fnailly
'cleanup code
End Try

hope this helps..
Imran.
 
Imran,
IMHO the Global Exception handlers in .NET are far simpler then even a
common routine, as you only hook up the Global Exception handlers once, then
you don't need to add the call to the common routine in 300 other routines!

Check out my other post & the article I referenced, you might change your
mind.

Hope this helps
Jay
 
Jay.....I took your advice. I'm pretty close here. It was quite simple even
for a n00b like me. I do have a question, however. Here is the code from my
sub main:

Sub main()
AddHandler Application.ThreadException, AddressOf myErrorHandler
Application.EnableVisualStyles()
Application.DoEvents()
Try
Execution code
Catch ex As Exception
Dim strInputE As String = Application.StartupPath & "\Error.txt"
Dim srE As StreamWriter = File.AppendText(strInputE)
srE.WriteLine(vbCr)
srE.WriteLine(vbCr)
srE.WriteLine(DateTime.Now)
srE.WriteLine("------------------")
srE.WriteLine(ex.ToString)
srE.Close()
MsgBox("An Error has occurred. Please check the file " &
Application.StartupPath & "\Error.txt for details.", MsgBoxStyle.Critical,
CPViewer")
Exit Sub
End Try
End Sub

And here is what I get when an exception is thrown by this code in the sub
main:

8/16/2004 8:27:10 PM
------------------
System.NullReferenceException: Object reference not set to an instance of an
object.
at CPViewer.mStartup.main()

Now....Here is my Global Code that I placed in a module:

Imports System
Imports System.IO
Imports System.Threading
Module myErrors
Public Sub myErrorHandler(ByVal sender As Object, ByVal e As
System.Threading.ThreadExceptionEventArgs)
Dim ex As Exception = e.Exception
Dim strInputE As String = Application.StartupPath & "\Error.txt"
Dim srE As StreamWriter = File.AppendText(strInputE)
srE.WriteLine(vbCr)
srE.WriteLine(vbCr)
srE.WriteLine(DateTime.Now)
srE.WriteLine("------------------")
srE.WriteLine(ex.ToString)
srE.Close()
MsgBox("An Error has occurred. Please check the file " &
Application.StartupPath & "\Error.txt for details.", MsgBoxStyle.Critical,
"CPViewer")
End Sub
End Module

And here is what I get when an exception is throwh by a control within a
form:

8/16/2004 8:18:01 PM
------------------
System.ArgumentException: Invalid parameter used.
at System.Drawing.Bitmap..ctor(String filename)
at CPViewer.Form1.OpenLayout()
at CPViewer.Form1.mnuMainFileOpen_Click(Object sender, EventArgs e)
at System.Windows.Forms.MenuItem.OnClick(EventArgs e)
at System.Windows.Forms.MenuItemData.Execute()
at System.Windows.Forms.Command.Invoke()
at System.Windows.Forms.Control.WmCommand(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
at System.Windows.Forms.ContainerControl.WndProc(Message& m)
at System.Windows.Forms.Form.WndProc(Message& m)
at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg,
IntPtr wparam, IntPtr lparam)

Why is the second error so much more descriptive. Also, do you have any
other suggestion on anything I may have missed?

Thanks for your time,
John
 
Oh yes - I did change my mind :)
I wasn't too familiar with global exception handlers.
Mine was just a 'at the top of the head' solution.
Thanks for the info, Jay!

Imran.
 
Imran,

I would not say that your approach is wrong, (maybe the word common can be
misleading, however when you read it as I used bellow I think it is in the
right context).

I think that your approach is the right OOP approach where relying on a
common errorhandler is in my opinion wrong.

Every created reusable class needs to have the right errorprocedures.
Therefore I do not like the approach of "common" errorhandlers for a
complete project. Although classes can reuse standard "common"
errorprocedures.

Just my thought.

Cor
 
John,
Why is the second error so much more descriptive. Also, do you have any
other suggestion on anything I may have missed?

The second error is not that it is so much more descriptive, it is that the
call stack is that much more deeper. All the indented lines that start with
" at" is an entry in the call stack, Window Forms apps event handlers can
have rather deep stack levels...

Also different exception can include further information, such as the
ArgumentOutOfRangeException.

Rather then duplicate:
Dim strInputE As String = Application.StartupPath & "\Error.txt"
Dim srE As StreamWriter = File.AppendText(strInputE)
srE.WriteLine(vbCr)
srE.WriteLine(vbCr)
srE.WriteLine(DateTime.Now)
srE.WriteLine("------------------")
srE.WriteLine(ex.ToString)
srE.Close()
MsgBox("An Error has occurred. Please check the file " &
Application.StartupPath & "\Error.txt for details.", MsgBoxStyle.Critical,
CPViewer")

In both places I would have the Sub Main call your event handler directly,
or have Sub Main & the event handler call a common routine, simply to ensure
both are totally consistent. (also I like short Sub Main's not sure why).

Sub main()
AddHandler Application.ThreadException, AddressOf myErrorHandler
Application.EnableVisualStyles()
Application.DoEvents()
Try
Execution code
Catch ex As Exception

Application_ThreadException(Nothing, New
Threading.ThreadExceptionEventArgs(ex))
Exit Sub
End Try
End Sub

Hope this helps
Jay
 
Jay B. Harlow said:
John,

The second error is not that it is so much more descriptive, it is that the
call stack is that much more deeper. All the indented lines that start with
" at" is an entry in the call stack, Window Forms apps event handlers can
have rather deep stack levels...

Also different exception can include further information, such as the
ArgumentOutOfRangeException.

Rather then duplicate:

In both places I would have the Sub Main call your event handler directly,
or have Sub Main & the event handler call a common routine, simply to ensure
both are totally consistent. (also I like short Sub Main's not sure why).



Application_ThreadException(Nothing, New
Threading.ThreadExceptionEventArgs(ex))

Duh, I should have known that.
Hope this helps
Jay

It all helps a lot. Thanks for your help Jay,
John
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top