PDA

View Full Version : Global Error Handler



xCav8r
06-15-2005, 11:03 AM
Is anyone here using a global error handler for Word?

MOS MASTER
06-15-2005, 11:22 AM
Is anyone here using a global error handler for Word?
Hi, :yes

Well don't know what you mean by a global error handler?

I always use a the same error handling function over and over again in all my procedures.

You can have it pop-up a msgbox or have it print an error log. I'm not on my own computer now so can't access my own errorhandler function.

But found something like it:
http://www.vb123.com/toolshed/04_accvb/globalerrorhandling.htm

Is this what you're looking for? :whistle:

Howard Kaikow
06-15-2005, 01:50 PM
Is anyone here using a global error handler for Word?

in general, a global error handler is a very bad way to code.
it is far better to have localized handlers that know the specifics of the errors for each procedure.

a global handler is less flexible and tends to produce fesghetti code.

one of the real attractions if the .net languages is try ... catch.

MOS MASTER
06-15-2005, 02:05 PM
Hi Howard, :yes

Yes indeed this is very true.
If you know what could happen then you should provide for that in your error handling.

The way I use a global handler as stated was for a error log. (that is if I understood the question) And mostly those errors that you didn't expect and have the log state in which part of the stack the error occured.

This very handy cause people can send it over to you and could help with debugging from a distance.

But of course things you can expect should be handled in a normal Select Case statement for the error nr on Case Else I like to go to the error log.

Later..:whistle:

xCav8r
06-15-2005, 02:11 PM
"Global" was a poor choice of words. I'm doing everything now at the local level, but I was curious if anyone had developed a nifty routine that accepted all unhandled errors from individual routines for logging and/or messaging along with other relevant info. I remember seeing something on the web that did this and also looked at the stack to get the offending procedure.

I'd love to use VS Tools for Office, but my current contract is to write all this stuff in VBA. :cry2:

MOS MASTER
06-15-2005, 02:20 PM
Well I should have something like that so I'll be sure to look it up for you. :yes

MOS MASTER
06-15-2005, 02:25 PM
Well I'm not here tomorrow so I decided to just find a good one for you on the MSDN.

This does exactly what you want:Click here (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/modcore/html/deconloggingerrorstotextfile.asp)

Enjoy! :whistle:

xCav8r
06-15-2005, 02:43 PM
Yes, this is great. The only thing it's lacking is grabbing the proc name from the stack. Thanks, Moose.

MOS MASTER
06-15-2005, 02:48 PM
Yes, this is great. The only thing it's lacking is grabbing the proc name from the stack. Thanks, Moose.
Well your Most welcome...

The Moose? O well a Moose lives in the Forest and a MOS MASTER in a FORUM! :rofl:

Could you explain why the function should pick the procedure from the stack?
Whit that code you don't need that..your calling this code from each procedure and in the call you give a optional parameter with the name of the sub?

You have to call it anyway why not give the name while your add it? :whistle:

Howard Kaikow
06-15-2005, 02:55 PM
"Global" was a poor choice of words. I'm doing everything now at the local level, but I was curious if anyone had developed a nifty routine that accepted all unhandled errors from individual routines for logging and/or messaging along with other relevant info. I remember seeing something on the web that did this and also looked at the stack to get the offending procedure.

I'd love to use VS Tools for Office, but my current contract is to write all this stuff in VBA. :cry2:

There's two separate issues:

1. Where to do the actual error checking. At the local level is best.
2. How to create error logs. That's most easily done by having each separate error handler pass its info to a single separate procedure called by all the error handlers.

For use with VBA, VB 6 is easier to use than VB .NET.

For Office programming, I see no reason to use the .NET lanhuages, as long as VBA is still the prime macro language for Office, unless there is some functionalty that is not attainable via VB 6. Not to mention, tho I will because it is very important, VB 6 code can be compiled and protected from prying eyes, not so with VB .NET and C#.

xCav8r
06-15-2005, 02:58 PM
Moss :rofl: , only wanting to avoid having to copy and paste the name and enquote it. Also, that page I had read (unless my memory is getting imaginative) suggested that you could capture the order of procedures called. That would be helpful to me, since I have oodles of routines in these global templates I'm making. If I'm going to recreate the error, I have to find out which routine started the whole process.

xCav8r
06-15-2005, 03:21 PM
1. Where to do the actual error checking. At the local level is best.

1. I agree. In fact, I don't know how you could effectively do it at a global level. I have religiously adhered to the model (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/modcore/html/deconhandlingerrors.asp)I learned from the autocode of those nasty Access wizards back in the day:


Function ProcedureName(ArgumentList) As DataType
' Procedure comments.
' Declare local variables and constants.

On Error GoTo ProcedureName_Err
' Procedure code.
.
.
.
ProcedureName = True (or some other return value)
ProcedureName_End:
' Cleanup code that closes open files and sets object variables = Nothing.
Exit Function
ProcedureName_Err:
ProcedureName = False
Select Case Err.Number
Case AnticipatedError#1
' Handle error #1.
Case AnticipatedError#2
' Handle error #2.
Case UnAnticipatedErrors
' Handle unanticipated error.
Case Else
' Handle unforseen circumstances.
End Select
Resume ProcedureName_End
End Function



2. How to create error logs. That's most easily done by having each separate error handler pass its info to a single separate procedure called by all the error handlers.

Right! This is what I would like to discuss. I'm very curious what other people are doing for this.


For use with VBA, VB 6 is easier to use than VB .NET.

For Office programming, I see no reason to use the .NET lanhuages, as long as VBA is still the prime macro language for Office, unless there is some functionalty that is not attainable via VB 6. Not to mention, tho I will because it is very important, VB 6 code can be compiled and protected from prying eyes, not so with VB .NET and C#.

You mentioned this before, and I agree that VB 6 has the aforementioned advantages over VB .NET, but some of us are restricted to what we have. As for VBA over .NET for Office programming...http://blogs.officezealot.com/chris/archive/2004/03/26/1092.aspx

:sandbox:

MOS MASTER
06-15-2005, 03:36 PM
Moss :rofl: , only wanting to avoid having to copy and paste the name and enquote it. Also, that page I had read (unless my memory is getting imaginative) suggested that you could capture the order of procedures called. That would be helpful to me, since I have oodles of routines in these global templates I'm making. If I'm going to recreate the error, I have to find out which routine started the whole process.
Hi, :yes

Yes I understand what you mean but this code has to be used within each sub/function, etc...And then it will work properly.

I don't know if it's possible to get the procedure from the stack that's causing the error by code(handler)

I know there's a tool within the VBE to call the stack but if you could do something like that with code??? (Have never looked for it..so if there's time I'm on it)

Enough for one day...tada..:whistle:

MOS MASTER
06-15-2005, 03:41 PM
This looks promissing as well: Click (http://www.fmsinc.com/tpapers/vbacode/Debug.asp)

Later..:whistle:

xCav8r
06-15-2005, 03:55 PM
Yeah! That last link treats the same material I was talking about. You da mouse, mos.

MOS MASTER
06-15-2005, 04:12 PM
Yeah! You da mouse, mos.
Nah..you silly..You are! :rtfm:

You're welcome and enjoy your debugging. (Wil have a play with that last article myself..like that one) :whistle:

xCav8r
06-15-2005, 08:59 PM
I'm working on the last article myself. Prolly gonna combine that with the first then develop some options for logging and messaging. Initially I'll log to a file, but I'll enhance it as I have time with the ability to log to Access, SQL Server 2000, MySQL, and SQLite.

It looks as if there is no way to avoid cutting and pasting the the procedure name following what the article says. Looks like the call stack is only available for viewing. Bummer. Since there's cutting and pasting required, however, that bring up another issue where I'd like some input/discussion. I use a template (so to speak) for my procedures...

Sub RoutineName()
'Comments: what it does and how to use it
'Local Variables and Constants

On Error GoTo RoutineName_Error:

RoutineName_Exit:
Exit Sub

RoutineName_Error:
'Local Error Handling
'Unexpected Error Handling
MsgBox Err.Number & ": " & Err.Description
Resume RoutineName_Exit
End Sub


I usually cut and paste this into new routines, changing RoutineName obviously. I do this for every procedure without exception, but I do it out of habit. It certainly would be easier to use generic label names like those suggested in the second article...


Sub AdvancedErrorStructure()
'Comments: What the current procedure does and how you use it
'Local Variables and Constants

If gcfHandleErrors Then On Error GoTo PROC_ERR
PushCallStack "AdvancedErrorStructure"

PROC_EXIT:
PopCallStack
Exit Sub

PROC_ERR:
' Local Error Handling
' Unexpected Error Handling
GlobalErrHandler
Resume PROC_EXIT
End Sub


I'm considering adopting these generic labels. What do the rest of you use?

Howard Kaikow
06-15-2005, 09:02 PM
1. I agree. In fact, I don't know how you could effectively do it at a global level. I have religiously adhered to the model (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/modcore/html/deconhandlingerrors.asp)I learned from the autocode of those nasty Access wizards back in the day:

One could allow all errors to filter up to an error handler in another procedure, but that's bad coding.


Right! This is what I would like to discuss. I'm very curious what other people are doing for this.

There's only 1 way.
Create a log file when the program starts and have ALL error handlers write info to that file, perhaps info to that od a previis session.



You mentioned this before, and I agree that VB 6 has the aforementioned advantages over VB .NET, but some of us are restricted to what we have. As for VBA over .NET for Office programming...http://blogs.officezealot.com/chris/archive/2004/03/26/1092.aspx


VSTO Is much ado about nothing.

When Office is fully .NET-ozed so macros can actually be written in the .NET languages, that would be a time to consider using the .NET languages instead of VB 6.

xCav8r
06-15-2005, 09:33 PM
One could allow all errors to filter up to an error handler in another procedure, but that's bad coding.

We're on the same page here. A truly global error handler in VBA seems like it would be unwieldy. If it were to be effective, I don't think it would be cost-beneficial.


There's only 1 way.
Create a log file when the program starts and have ALL error handlers write info to that file, perhaps info to that od a previis session.

Judging from your comments, you're obviously more experienced than the average VBA programmer. I would be interested in learning more from you on this subject. Do you normally write all errors to a log--even handled ones? If you are logging handled errors, how have you benefited from that? Got any tips, comments, or code to share? Do you log to a text file, database, or something else? What sort of information do you store?

Howard Kaikow
06-15-2005, 10:41 PM
We're on the same page here. A truly global error handler in VBA seems like it would be unwieldy. If it were to be effective, I don't think it would be cost-beneficial.

I'd have to go check the bookmark in the most recent book I've been reading (a C# book) to find out what page I'm on.

Although the mechanisms available may be different, error handling in VBA is really no different than in any other programming language.


Judging from your comments, you're obviously more experienced than the average VBA programmer. I would be interested in learning more from you on this subject. Do you normally write all errors to a log--even handled ones? If you are logging handled errors, how have you benefited from that? Got any tips, comments, or code to share? Do you log to a text file, database, or something else? What sort of information do you store?

The tip is to write the code in such a way to minimize error handling.
I very rarely find the need to check for specific errors.

Proper program design greatly reduces the chance of unexpected errors.
Usually, when I test for an error, I do not care what is the error.

For example, I've recently been investing the behavior of PowerPoint and I needed to find out whether PowerPoint was already runningg, so I included On Error Resume Next right before the GetObject statemant and juat test whether ANY error occurred. If an error occurred, don't care what it is, then I create a New instance of PowerPint, if there was no error, then PowerPoint was already running and I merrily roll along using the running instance.

xCav8r
06-16-2005, 06:43 AM
I'd have to go check the bookmark in the most recent book I've been reading (a C# book) to find out what page I'm on.

:bgrlaugh:

You know, now that I go back and read what you wrote, I see I misunderstood. When you said "Create a log file when the program starts and have ALL error handlers write info to that file" I incorrectly understood "record ALL errors in the log", which prompted those first two questions. Sorry 'bout that. :doh:

MOS MASTER
06-16-2005, 12:55 PM
I'm working on the last article myself. Prolly gonna combine that with the first then develop some options for logging and messaging. Initially I'll log to a file, but I'll enhance it as I have time with the ability to log to Access, SQL Server 2000, MySQL, and SQLite.

Hi, :yes

Sound great to me I had no time yet.
Be sure to put the finished error logging code over here. I'd love to try it out! :whistle:

xCav8r
06-17-2005, 04:24 PM
I'm rather fond of the method of recreating the stack that the second article suggests. I've done that now for several projects I'm working on. Not a little amount of work either. I thought I'd share something I've added to it. By just pushing the procedure name onto the stack, you don't get the module name or project. Not a big deal for something that's small, but if you're spanning several projects, that could get confusing.

So, I've created constantsto capture the project name and module name, then a little function to concatenate them with the procedure name to push to the stack recreator. My default procedure now looks something like this...

Sub RoutineName()
'Comments: What this routine does and how to use it

If gcfHandleErrors Then On Error GoTo RoutineName_Error
PushCallStack ConcatenateProjectNameAndModuleNameAndProcedureName( _
gcstrProjectName, _
mcstrModuleName, _
"RoutineName")

' << Your code here >>

RoutineName_Exit:
PopCallStack
Exit Sub

RoutineName_Error:
Select Case Err.Number
'Local Error Handling
Case Else
GlobalErrHandler
End Select
Resume RoutineName_Exit
End Sub


And here's the function I'm currently using...

Function ConcatenateProjectNameAndModuleNameAndProcedureName( _
ProjectName As String, _
ModuleName As String, _
ProcedureName As String)

' This function should be called by every procedure with error handling to
' concatenate ProjectName.ModuleName.ProcedureName to use for the log
' called by the global error handler. A public constant should be declared
' to house the project name, and a module level constant should be used
' to house individual module names to reduce the amount of customization
' required per procedure.

If gcfHandleErrors Then On Error GoTo _
ConcatenateProjectNameAndModuleNameAndProcedureName_Error
PushCallStack gcstrProjectName _
& mcstrModuleName _
& ".ConcatenateProjectNameAndModuleNameAndProcedureName"
ConcatenateProjectNameAndModuleNameAndProcedureName = ProjectName _ & "." & ModuleName _
& "." & ProcedureName

ConcatenateProjectNameAndModuleNameAndProcedureName_Exit:
PopCallStack
Exit Function

ConcatenateProjectNameAndModuleNameAndProcedureName_Error:
Select Case Err.Number
Case Else
GlobalErrHandler
Resume ConcatenateProjectNameAndModuleNameAndProcedureName_Exit
End Select
End Function

Log sample...


Error Number: 11
Error Description: Division by zero
CallStack (0): TestLogError
Date/Time: 6/17/2005 7:32:40 PM
User: Marco

Error Number: -2147467259
Error Description: [Microsoft][ODBC Excel Driver] '(unknown)' is not a valid
path. Make sure that the path name is spelled correctly and that you are
connected to the server on which the file resides.
CallStack (0): RealEstateStartup.modDataMerge.MergeTemplateWithData
CallStack (1): RealEstateStartup.modLoadConfiguration.LoadFileExtenions
CallStack (2): CodeLibrary.modAdoOperations.ReadDataFromWorkbook
Date/Time: 6/17/2005 8:03:48 PM
User: Marco

Error Number: 76
Error Description: Path not found
CallStack (0): RealEstateStartup.modDataMerge.MergeTemplateWithData
CallStack (1): CodeLibrary.modFTP.GetFile
Date/Time: 6/17/2005 8:41:18 PM
User: Marco

I'm planning to add a few new things to the log:

Message sent to user
My own error description (in this case intended to be used to troubleshoot problems by employees of my client after my work for them is done)
Line number that generated error (don't have them in the code right now)

MOS MASTER
06-18-2005, 10:55 AM
Hi, :yes

Looks good to me. Will have a play with it later. :whistle:

xCav8r
06-18-2005, 12:57 PM
I need a good line number generator now. The one I have inserts blank lines and numbers those. No good for Erl. Suggestions?

MOS MASTER
06-18-2005, 01:00 PM
I need a good line number generator now. The one I have inserts blank lines and numbers those. No good for Erl. Suggestions?
Hi, :yes

Don't understand your question..what do you mean?

The one you have? which one is that?
More detail please...:whistle:

xCav8r
06-18-2005, 01:08 PM
http://www.billdawson.com/downloads/files/OfficeDevAddin.html

MOS MASTER
06-18-2005, 01:34 PM
http://www.billdawson.com/downloads/files/OfficeDevAddin.html
And that should mean what to me? :whistle:

xCav8r
06-18-2005, 01:40 PM
Sorry, I thought you were asking what I was using to put line numbers into VBA. The add-in at that link is what I'm currently using, but it inserts blank lines and numbers those, and so I can't log the line where the error originated with Erl.

Sub StartBDAddIn()
30
On Error GoTo errorhandler
40
Dim oneAddin As COMAddIn
50
For Each oneAddin In Application.COMAddIns
60
If StrComp(oneAddin.ProgID, "bOffDevLib.bOffDevWord", vbTextCompare) = 0 Then
70
oneAddin.Connect = True
80
End If
90
Next
100
Exit Sub
110
errorhandler:
120
MsgBox "Error loading bOffDev COM Add-in: " & Err.Description
130
Err.Clear
140
Exit Sub
End Sub

MOS MASTER
06-18-2005, 01:55 PM
Hi, :yes

Ah Ok got it now.
I'll read back in to things and come back to this one.

I've never uses Err lines myself but I know you have to have linenummers in ALL of your code. Do you have that?

Later..:whistle:

MOS MASTER
06-18-2005, 02:18 PM
Hi, :yes

Well I'm not gonna use that addin myself thus not installing it!

I did a little test if Err lines are easy to retrieve and they are.
The test I did:
Option Explicit

Sub GenerateError()
Dim iNum As Integer
Dim iDenom As Integer
Dim iResult As Integer

On Error GoTo Err_GenerateError
1: iNum = 5
2: iDenom = 0
3: iResult = iNum / iDenom

End_GenerateError:
Exit Sub

Err_GenerateError:
MsgBox Err.Description & _
" (" & Err.Number & ") occured on line " & Erl()

Resume End_GenerateError
End Sub


So it seams quite easy to retrieve it and thus usefull. I think I'm gonna use it myself from now! :whistle:

xCav8r
06-18-2005, 02:32 PM
I only installed the addin for the line numbering, but because it adds blank lines as it numbers, it's not what I'm looking for. If you find something that numbers the code as you did in your example, I would be interested. I have found a number of things that add line numbers that cost $$$, but if I can find one for free, I'd rather use that. ;)

MOS MASTER
06-18-2005, 02:37 PM
I only installed the addin for the line numbering, but because it adds blank lines as it numbers, it's not what I'm looking for. If you find something that numbers the code as you did in your example, I would be interested. I have found a number of things that add line numbers that cost $$$, but if I can find one for free, I'd rather use that. ;)
Ah..You're looking for a free tool!

Well I like those as well! :tease:

I use this VBE addin: http://www.mztools.com/v3/mztools3.htm
And it does produce or remove line numbers or removes them...but if it does it the way you want it to???

Enjoy! :whistle:

xCav8r
06-18-2005, 02:44 PM
You da man, Mousse!!!!!!!!!! Working like a charm. Nice add-in.

MOS MASTER
06-18-2005, 02:46 PM
You da man, Mousse!!!!!!!!!! Working like a charm. Nice add-in.
Yepz..me like it a lot as well! You're Welcome! :beerchug:

Mousse!!! right back at yah! :whip

xCav8r
06-18-2005, 02:55 PM
I love the ability to control the auto error handling. :thumb

MOS MASTER
06-18-2005, 02:58 PM
I love the ability to control the auto error handling. :thumb
Me too...I'm sure it has much more tools you'd love! :yes

xCav8r
06-18-2005, 03:02 PM
I'm going nuts. How have I lived without this?????????????????

MOS MASTER
06-18-2005, 03:07 PM
I'm going nuts. How have I lived without this?????????????????
Well You've actually learned more becuase you had to do everything manualy!!

Now you have this great free tool you can automate a lot of things and so your fingers will finaly get that well deserved rest! :neener:

xCav8r
06-18-2005, 08:25 PM
Got it working now with Access and SQL Server 2000. Before I do any more, since I'm going to submit this for a KB entry, I thought I'd solicit suggestions for other information to capture. Here's what I'm currently tracking:

Error Number
Error Description (from scripting engine)
Call Stack (ProjectName.ModuleName.ProcedureName)
Line Number originating error
Date/Time Stamp
Windows Account Name
Message that the user saw
Optional message from the developer to troubleshooter
Preview of connection to Access with DAO...

Case gcintLogToAccess
strPathToDatabase = "C:\Temp\vba_error_log.mdb"
Set dbErrorLog = OpenDatabase(strPathToDatabase)
End Select

strSQL = "SELECT cs.lngIncidentID, " _
& "cs.intCallStackPosition, " _
& "cs.strCallStackProcedure " _
& "FROM tblErrorCallStacks AS cs;"
Set rstErrorCallStacks = dbErrorLog.OpenRecordset(strSQL)

strSQL = "SELECT ei.lngIncidentID, ei.lngErrorNumber, " _
& "ei.strErrorDescription, ei.datTimeStamp, " _
& "ei.strDevComment, ei.strUserMessage, " _
& "ei.intLineNumber, ei.strWindowsUser " _
& "FROM tblErrorIncidents AS ei;"
Set rstErrorIncidents = dbErrorLog.OpenRecordset(strSQL)

With rstErrorIncidents
.AddNew
.Fields!lngErrorNumber = lngErrorNumber
.Fields!strErrorDescription = strErrorDescription
.Fields!datTimeStamp = Now
.Fields!strDevComment = strDevComment
.Fields!strUserMessage = UserMessage 'parameter of procedure
.Fields!intLineNumber = intLineNumber
.Fields!strWindowsUser = GetUserName 'function in another module
.Update
.MoveLast
lngIncidentID = .Fields!lngIncidentID
.Close
End With

intCounter = 1
With rstErrorCallStacks
For Each varCallStack In mastrCallStack
If varCallStack <> "" Then
.AddNew
.Fields!lngIncidentID = lngIncidentID
.Fields!intCallStackPosition = intCallStackPosition
.Fields!strCallStackProcedure = varCallStack
.Update
End If
intCounter = intCounter + 1
Next varCallStack
End With

MOS MASTER
06-18-2005, 10:41 PM
Got it working now with Access and SQL Server 2000. Before I do any more, since I'm going to submit this for a KB entry, I thought I'd solicit suggestions for other information to capture. Here's what I'm currently tracking:

Error Number
Error Description (from scripting engine)
Call Stack (ProjectName.ModuleName.ProcedureName)
Line Number originating error
Date/Time Stamp
Windows Account Name
Message that the user saw
Optional message from the developer to troubleshooter

Hi, :yes

Yepz looking good and I can't wait to get my hands on reviewing that kb entry!

I would include the Computername in my errorlog.
You could use:
MsgBox Environ("COMPUTERNAME")
Depending your needs theres much more great data you can get from Environ function!

Also if you're code is spanning multiple projects I'd advice to use: Err.Source (look it up it can hold the object/project/class causing the error)

I can't think of anything else for now because you're covering so much more then I normally do. I think this entry will be very handy.

Later..:whistle:

fumei
06-20-2005, 09:29 AM
Right on Howard. In essense you are keeping to your local error handling dictum. Locally speaking, if the issue is: PowerPoint running - Yes? No?, then who cares what the error is with a No? It is No, so you make an instance. If it is Yes, you use that one.

The only real other possibility with error handling a No would be a check to see if there IS a PowerPoint to make an instance of. Not likely the case, but what if PowerPoint was not installed? You would an error (not running), but you would get another error trying to make a new instance.

xCav8r
06-20-2005, 06:11 PM
At the risk of sounding argumentative but only wanting to get a discussion going where we can learn from one another, I'll say I agree that good programming means anticipating as many possibilities as can be imagined and handling them in the body of your code so that they don't become errors, but I also recognize that you can't always get the sort of information that you want by testing conditions. To avoid duplicating a menu item, for example, I might attempt to delete it (in case it already exists) before trying to add it. Along that line, it seems to me that there will always be a need for handling specific errors--and that sort of thing is best when handled at the procedure level. I haven't disagreed with that concept in this thread.

Those things said, despite how much I try, it's irresponsible to assume that I've planned for every possibility. When I'm working with complex projects, especially when that's in a team environment, the potential for unanticipiated errors increases dramatically. In such cases, I think a global error handler is essential. First, it provides a means of documenting unhandled errors during the development process that acts as a convenient list of issues to address before unleashing your project on your users. Second, if done appropriately, it facilitates troubleshooting down the road.

Frankly, I'm surprised that there hasn't been more of an interest from the more experienced programmers on this forum. That might be the result of my own ignorance, but this seems like one of those best practice discussions that could be of benefit to all.

MOS MASTER
06-21-2005, 11:40 AM
Right on Howard. In essense you are keeping to your local error handling dictum. Locally speaking, if the issue is: PowerPoint running - Yes? No?, then who cares what the error is with a No? It is No, so you make an instance. If it is Yes, you use that one.

The only real other possibility with error handling a No would be a check to see if there IS a PowerPoint to make an instance of. Not likely the case, but what if PowerPoint was not installed? You would an error (not running), but you would get another error trying to make a new instance.
Hi Gerry, :yes

Isn't this about this topic: http://www.vbaexpress.com/forum/showthread.php?goto=newpost&t=3302 :*)

MOS MASTER
06-21-2005, 11:44 AM
Frankly, I'm surprised that there hasn't been more of an interest from the more experienced programmers on this forum. That might be the result of my own ignorance, but this seems like one of those best practice discussions that could be of benefit to all.
Hi, :yes

did my last post give you any new ideas?

I think the majority of programmers write small programs that only need a little amount of error handling.

If you write a big program the capabilities of a good error handling and error log are of great need! In perticular from debugging from a distance...

So Please go ahead and make your routine perfect so we can all benifit from it. :whistle:

xCav8r
06-21-2005, 02:12 PM
hehe...thanks...and yes, lots of ideas, but I haven't picked it back up again.

MOS MASTER
06-21-2005, 02:14 PM
hehe...thanks...and yes, lots of ideas, but I haven't picked it back up again.
Ah Ok...welcome...But uhmss please don't wonder of to far or lose focus because I want you to submit that entry! :goofball:

xCav8r
06-21-2005, 09:40 PM
I won't wander too far, but it might be a while before I kick out something with which I'm satisfied. The benefit of the delay to VBAX KB users will be that it'll be incorporated shortly into various projects serving several hundreds of people, so the major kinks should be worked out prior to submission.

In the meantime, I've added err.source. For some reason I had thought that err.source always returned the name of the application, but I see now that I was mistaken. At any rate, I'm not sure that it adds anything at this point, since I push the call stack with ProjectName.ModuleName.ProcedureName before there is an error, and err.source is obviously only available after an error has arisen. I suppose I could send the err.source as a parameter to the global error handler, but I don't see any advantage to that method over what I'm currently using. Perhaps you have some thoughts on that matter.

I've also included a loop to enumerate everything in the environment table.

fumei
06-22-2005, 08:54 AM
Argumentative? Hardly. This is a serous discussion, and we have to be free to bring forth stuff.

I agree. But let's see if we can agree on terms. What exactly does a global error handler DO? Handle ALL errors? You could easily end up with a monster routine larger than the original app.

I think there are some differences in error types.

User Input CONTENT errors, I think, should be handled locally. If an input field requires numeric, and alpha is input, that should be trapped locally - at the procedure level. I do not see the need to pass those to a global error handling routine.

User Input LOGIC errors can be handled at a module level, as normally, after all the information is collected locally (with local error trapping), said information is processed. That is, it is passed along - to the document, or to another module. So, at this oint, the content itself is good, but when parsed logically with other elements, there may be errors. So before the current module finishes there should be final error trapping. This is not "global" really, but it is sort of....

Then finally, I guess there is true global error handling. This handles errors coming out of the modules themselves. It assumes the content of data elements is good (handled locally), the logic within the module is good (handled at module level), but now checks to see if the all the modules TOGETHER (or globally) are good.

Does this makes any sense? Topic is open for discussion.

I absolutely agree that team processing opens up the possibility of unanticipated errors.

MOS MASTER
06-22-2005, 10:34 AM
Hi, :yes

Take all the time you need! It's a good thing you're going to test it first in the field. The code will benefit from that.

For me personally the only errors I'm trully interested in are the ones I didn't anticipate!

That means that my select case will handle all of those foreseen and my error logging gets the ones I didn't. More important including the source in the stack and the Error line (Erl())

That would be sufficient. But like I said before if you want something to help you debugging from a distance the errorhandler couldn't be big enough.

Don't forget if you design your error handling wel you could also use a separate DLL to process the Error log. This could be slimmed down for a release version but if need be you could easily replace that with a bulkier one!

But the Error lines have to be in the code to begin with otherwise that trick won't work...

So yes I'm very interested in the way this global thingie is growing...

So for now I hope I've given you again some more water to grow! :whistle:

xCav8r
06-24-2005, 06:43 PM
I found another article with some useful information on the subject of error handling: http://www.developerfusion.com/show/1741/


What exactly does a global error handler DO? Handle ALL errors? You could easily end up with a monster routine larger than the original app.
This thread is long, and the worthy content is sporadic and convoluted, so I don't fault you for not having read all of the posts that gradually led to answers to the questions you pose here. http://www.vbaexpress.com/forum/images/smilies/tongue%202.gif500) {this.width=500;this.alt='Full View';}" border=0> (http://www.vbaexpress.com/forum/images/smilies/tongue%202.gif)

I admitted that global error handler was a slight misnomer, because it conveys to some the idea of a single error handler, which is not the concept I intended when I started the thread, and I apologize for not having been clearer up front. For the purposes of this discussion, global error handler refers to a set of routines that in conjunction respond to and log unhandled errors.


Does this makes any sense? Topic is open for discussion.
I?m not sure that I totally follow what you?re saying, but I think some of your comments might have been directed to a different notion of global error handler.

I group my procedures together with procedures that deal with similar things. For example, I have a standard module that does stuff with printers (gets information about available printers, selects trays, changes duplex settings, sends big print jobs in batches to avoid problems with memory limitations in certain printers, etc). Although some procedures work with others in the same module to achieve a goal, the same could be said of procedures across modules. And, because it?s not uncommon for a task to be accomplished using multiple procedures all in different modules, it?s difficult to conceive of something I could do at a module level (standard, not class) along the lines of what you described.


Don't forget if you design your error handling wel you could also use a separate DLL to process the Error log. This could be slimmed down for a release version but if need be you could easily replace that with a bulkier one!
That's a consideration, I think, for farther down the road.


But the Error lines have to be in the code to begin with otherwise that trick won't work...
Indeed. That'll need to be the last step before releasing a project that uses this error handling scheme.

Howard Kaikow
06-25-2005, 03:17 AM
At the risk of sounding argumentative but only wanting to get a discussion going where we can learn from one another, I'll say I agree that good programming means anticipating as many possibilities as can be imagined and handling them in the body of your code so that they don't become errors, but I also recognize that you can't always get the sort of information that you want by testing conditions. To avoid duplicating a menu item, for example, I might attempt to delete it (in case it already exists) before trying to add it. Along that line, it seems to me that there will always be a need for handling specific errors--and that sort of thing is best when handled at the procedure level. I haven't disagreed with that concept in this thread.

Those things said, despite how much I try, it's irresponsible to assume that I've planned for every possibility. When I'm working with complex projects, especially when that's in a team environment, the potential for unanticipiated errors increases dramatically. In such cases, I think a global error handler is essential. First, it provides a means of documenting unhandled errors during the development process that acts as a convenient list of issues to address before unleashing your project on your users. Second, if done appropriately, it facilitates troubleshooting down the road.

Frankly, I'm surprised that there hasn't been more of an interest from the more experienced programmers on this forum. That might be the result of my own ignorance, but this seems like one of those best practice discussions that could be of benefit to all.

Experienced programmers have learned how to write code that minimizes the need for "global error handlers".

It just takes time to learn how to do this.

The first step is to write modular code, i.e., isolate functionality into individual subs/functions.

As you write each sub/function, where needed, put a local error handler in the sub/function. You will be surprised at how rarely you will need such a handler.

For most tasks, you can get by without a local error handler just by using On Error Resume Next in the obvious places, and, where needed, checking for the error locally, not in an error handler.

In other cases, On Error Goto Somewhere will be used to skip blocks of code.

Rarely do I ever find a need to know the particular error number,

xCav8r
06-26-2005, 01:32 AM
Experienced programmers have learned how to write code that minimizes the need for "global error handlers".

I'm wondering if we're talking past one another in this thread. I explained what I meant by global error handler in my second post, and I reaffirmed that definition in my last post. I'll repeat what I wrote, because I don't think you read it. For the purposes of this discussion--at least when I use it--a global error handler refers to a group of procedures that work in conjunction to log unhandled errors. A global error handler does not mean a single error handler.

If, for some reason I'm mistaken, and you have understood this phrase in the way that I am using it, then I'd like to understand why you think it's good practice to assume that you've anticipated every possible error. That doesn't sound like something that an experienced programmer would do. In fact, it seems to me that only an inexperienced programmer would do this.

Futher, the very text I wrote--which you quoted--agrees with the concept of this statement. I've already stated that "good programming means anticipating as many possibilities as can be imagined and handling them in the body of your code so that they don't become errors". Either you're not reading what I have written, or I haven't understood your responses. If the latter is the case, then it would be helpful to have more detail from you to explain where I've gone wrong.


The first step is to write modular code, i.e., isolate functionality into individual subs/functions.

I already do this. If I don't do it when I write it, I invariably alter it after. When I write any code--regardless of the language--I always try to make it reusable. If anything, I'm guilty of doing that too often, even with projects that'll never be modified or have elements repeated. That's my methodology.


As you write each sub/function, where needed, put a local error handler in the sub/function. You will be surprised at how rarely you will need such a handler.

This paragraph is what convinced me that you haven't read what I've written in this thread. If I anticipate an error that can be corrected, then I will will handle it at the procedure level. Sometimes I do this the hard way--though sometimes unnecessarily. For example, if I need to access a file, I check to see if the file exists using code, but I could simply test for err.number = 53 (and a few others), but I prefer to check it the file actually exists with a function I have written specificially for this purpose.

Still, I never assume that I have anticipated every possibility. That's why I want to log all unhandled errors.


For most tasks, you can get by without a local error handler just by using On Error Resume Next in the obvious places, and, where needed, checking for the error locally, not in an error handler.

If there had been any question in my mind about what you understand by global error handler, I think this text lays the question to rest. Resume next assumes the error is not fatal. When I anticipate such an error, then I'll resume next..but I'm not talking about anticipated errors.