15

I have VB6 application , I want to put some good error handling finction in it which can tell me what was the error and exact place when it happened , can anyone suggest the good way to do this

Onorio Catenacci
  • 14,928
  • 14
  • 81
  • 132
RBS
  • 3,801
  • 11
  • 35
  • 33

7 Answers7

31

First of all, go get MZTools for Visual Basic 6, its free and invaluable. Second add a custom error handler on every function (yes, every function). The error handler we use looks something like this:

On Error GoTo {PROCEDURE_NAME}_Error

{PROCEDURE_BODY}

    On Error GoTo 0
    Exit {PROCEDURE_TYPE}

{PROCEDURE_NAME}_Error:

   LogError "Error " & Err.Number & " (" & Err.Description & ") in line " & Erl & _
            ", in procedure {PROCEDURE_NAME} of {MODULE_TYPE} {MODULE_NAME}"

Then create a LogError function that logs the error to disc. Next, before you release code add Line Numbers to every function (this is also built into MZTools). From now on you will know from the Error Logs everything that happens. If possible, also, upload the error logs and actually examine them live from the field.

This is about the best you can do for unexpected global error handling in VB6 (one of its many defects), and really this should only be used to find unexpected errors. If you know that if there is the possibility of an error occurring in a certain situation, you should catch that particular error and handle for it. If you know that an error occurring in a certain section is going to cause instability (File IO, Memory Issues, etc) warn the user and know that you are in an "unknown state" and that "bad things" are probably going happen. Obviously use friendly terms to keep the user informed, but not frightened.

Kris Erickson
  • 33,454
  • 26
  • 120
  • 175
  • Kris--I wish I could give you two upvotes for that answer. Very good answer! – Onorio Catenacci Sep 22 '08 at 17:44
  • Why do you add an On Error Goto 0 before the Exit? My understanding is that when the Exit (Function|Sub) occurs the current error handler loses scope automatically. – Darrel Miller Sep 22 '08 at 17:56
  • Also, assuming the original poster does what you said, any calling routine is going to be oblivious to the fact that an error occurred and will continue processing. How do you recover from the error? – Darrel Miller Sep 22 '08 at 17:58
  • The On Error Goto 0 isn't necessary (I think it was a code optimization for VB5, but I can't remember), it was just part of the boiler plate code. Like I stated in the answer, this is just to handle unexpected errors. You should code for any errors that you can possibly expect. – Kris Erickson Sep 23 '08 at 04:22
  • 1
    +1, but I would also suggest throwing the error back to the caller in the error handler. Otherwise the caller will carry on in ignorance that the routine hasn't worked and might cause worse problems. Event handlers obviously shouldn't throw or they'll crash the app. – MarkJ Apr 16 '09 at 09:23
  • When you rethrow the error you can also use maero's idea to build in a stack trace. If the top-level event handlers show a message box, this means you have the stack trace right there without needing to view the logs. I've also noticed your current answer doesn't tell the user things have gone wrong – MarkJ Apr 16 '09 at 09:27
  • Where is it free? That link asks for $60+ – NeoTechni Aug 23 '21 at 18:46
  • @NeoTechni - This post is over 13 years old... It was free 13 years ago -- I am shocked it is still available. Even 13 years ago using VB6 was a terrible idea, using it now over 20 years since it was last updated is an even worse idea. – Kris Erickson Sep 22 '21 at 23:50
  • I use VB6 for a program that handles a ton of things, and dot NET for a companion app that merely forwards Win10 notifications to the VB6 app. The VB6 IDE running my program uses less RAM than the dot NET companion program. Performance matters in this case as it's a realtime OCR engine. So dot NET is out. – NeoTechni Sep 24 '21 at 00:32
14

a simple way without additional modules, useful for class modules:

pre-empt each function/subs:

On Error Goto Handler

handler/bubbleup:

Handler:
  Err.Raise Err.Number, "(function_name)->" & Err.source, Err.Description

voila, ghetto stack trace.

senshin
  • 10,022
  • 7
  • 46
  • 59
maero
  • 326
  • 2
  • 7
4

I use a home-grown Error.bas module to make reporting and re-raising less cumbersome.

Here's its contents (edited for length):

Option Explicit

Public Sub ReportFrom(Source As Variant, Optional Procedure As String)
    If Err.Number Then
        'Backup Error Contents'
        Dim ErrNumber As Long: ErrNumber = Err.Number
        Dim ErrSource As String: ErrSource = Err.Source
        Dim ErrDescription As String: ErrDescription = Err.Description
        Dim ErrHelpFile As String: ErrHelpFile = Err.HelpFile
        Dim ErrHelpContext As Long: ErrHelpContext = Err.HelpContext
        Dim ErrLastDllError As Long: ErrLastDllError = Err.LastDllError
    On Error Resume Next
        'Retrieve Source Name'
        Dim SourceName As String
        If VarType(Source) = vbObject Then
            SourceName = TypeName(Source)
        Else
            SourceName = CStr(Source)
        End If
        If LenB(Procedure) Then
            SourceName = SourceName & "." & Procedure
        End If
        Err.Clear
        'Do your normal error reporting including logging, etc'
        MsgBox "Error " & CStr(ErrNumber) & vbLf & "Source: " & ErrSource & vbCrLf & "Procedure: " & SourceName & vbLf & "Description: " & ErrDescription & vbLf & "Last DLL Error: " & Hex$(ErrLastDllError)
        'Report failure in logging'
        If Err.Number Then
            MsgBox "Additionally, the error failed to be logged properly"
            Err.Clear
        End If
    End If
End Sub

Public Sub Reraise(Optional ByVal NewSource As String)
    If LenB(NewSource) Then
        NewSource = NewSource & " -> " & Err.Source
    Else
        NewSource = Err.Source
    End If
    Err.Raise Err.Number, NewSource, Err.Description, Err.HelpFile, Err.HelpContext
End Sub

Reporting an error is as simple as:

Public Sub Form_Load()
On Error Goto HError
    MsgBox 1/0
    Exit Sub
HError:
    Error.ReportFrom Me, "Form_Load"
End Sub

Reraising an error is as simple as calling Error.Reraise with the new source.

Although it is possible to retrieve the Source and Procedure parameters from the call stack if you compile with symbolic debug info, it's not reliable enough to use in production applications

rpetrich
  • 32,196
  • 6
  • 66
  • 89
  • Nice idea but you should really put Exit Sub above "HError:" in your example Form_Load routine. – MarkJ Apr 16 '09 at 09:24
  • Good catch MarkJ! For the sake of completeness, I've added that – rpetrich Apr 16 '09 at 10:01
  • As I pointed out in another incarnation of this question: I see one big drawback here. Now, if I do this, all runtime errors are handled. Debugger will not stop application at error location. Instead it will stop inside error handler in some other procedure down the stack. So this method helps with a I-have-no-debugger-in-production-environment scenario but breaks normal work with VB6 IDE. – Tomek Szpakowicz Jul 10 '09 at 13:00
  • For debugging in the IDE, one should always set it to break on all errors (of course, that assumes normal program flow does not generate errors) – rpetrich Jul 10 '09 at 18:04
3

ON ERROR GOTO

and the

Err

object.

There is a tutorial here.

Csa77
  • 649
  • 13
  • 19
Joe Skora
  • 14,735
  • 5
  • 36
  • 39
  • @symbiont, thanks, I've replaced it with another one for now, but VB6 links will probably get more and more scarce due to it's age. – Joe Skora Jan 06 '17 at 16:39
  • thanks. yea you're right of course. unfortunately i sometimes have to use it for work (i hope its gone soon haha) – symbiont Jan 09 '17 at 16:38
  • Received a "site off-line (due to technical reasons)" message upon visiting link. – clamum Oct 11 '18 at 14:32
  • @clamum Thanks, that appears to be temporary at the moment, but I'll try to update the answer if it doesn't come back. – Joe Skora Oct 12 '18 at 13:23
1

Yes, take Kris's advice and get MZTools.

You can add line numbers to section off areas of complex procedures, which ERL will report in the error handler, to track down which area is causing the error.

10
    ...group of statements
20
    ...group of statements
30
    ...and so on
Gordon Bell
  • 13,337
  • 3
  • 45
  • 64
1

Use on

dim errhndl as string
on error goto errhndl
errhndl:
msgbox "Error"
  • 1
    Please describe your answer – warunapww Aug 23 '16 at 21:58
  • sometimes you have a error you want to skip, but if you do on error resume next you dont even know there was a error, the reason I like to use this is it continues but it tells you there was a error –  Aug 23 '16 at 22:03
0

Use the On Error statement and the Err object.

Robert S.
  • 25,266
  • 14
  • 84
  • 116