I have some code with various "On Error Goto" error handlers in a few places to handle some broken third party hardware. I was getting an overflow error (read from the Err variable) in a routine that doesn't have an error trap but is called by a routine that does. I always thought error traps were only valid in the routine they were declared, but it looks like an error in a subroutine can cause it to go to the calling function's error trap.
So I turned off the calling function's error trap and found my overflow and all is well. But before I did that, I spent some time trying to find a programatic way to get VB to return to its default error handling inside that routine (so I wouldn't have to modify outside code to debug), but I couldn't. The only error commands I could find:
On Error GoTo [label]
On Error Resume Next
On Error Goto 0
On Error GoTo -1
all turn on the manual error handling - is there a way to turn it off (back to the VB6 default)?
This is explained thoroughly in the VB6 manual under Error Handling Hierarchy. On Error Goto 0
disables the error handler in the current procedure, not in the procedures that called it.
If an error occurs in a procedure and
this procedure doesn't have an enabled
error handler, Visual Basic searches
backward through the pending
procedures in the calls list — and executes the first
enabled error handler it finds. If it
doesn't encounter an enabled error
handler anywhere in the calls list, it
presents a default unexpected error
message and halts execution.
As others have said, you can go to Tools-Options-General tab and choose Break on all errors. That effectively disables all your On Error statements - the IDE will break immediately on every error.
That can be irritating if your VB6 code throws errors as part of normal operation. For instance when you check whether a file exists, or when the user presses cancel in a common dialogue. You don't want the IDE to break every time on those lines. But you might have boilerplate error handlers in all your event handling procedures, to stop the program crashing out on unexpected errors. But they are a nuisance when you're debugging problems because the IDE doesn't break on the line with the error. One trick is to switch off those error handlers when running in the IDE, but keep them in the built executable. You do it like this.
Drop these functions into a module.
Public Function InIDE() As Boolean
Debug.Assert Not TestIDE(InIDE)
End Function
Private Function TestIDE(Test As Boolean) As Boolean
Test = True
End Function
Then you can write your error handlers like this.
Private Sub Form_Load()
If Not InIDE() Then On Error Goto PreventCrashes
<lots of code>
Exit Sub
PreventCrashes:
<report the error>
End Sub
Pinched from here. Another tip - use the free add-in MZTools to automatically add these boilerplate error handlers. For production-quality code, you could go further and put an error handler in every routine to create a ghetto stack trace. You might also log the errors immediately in every error handler.
EDIT: Ant has correctly pointed out that On Error Goto -1
is a VB.Net statement and isn't valid in VB6.
EDIT: Arvo and OneNerd have written answers with some interesting discussion of emulating Finally teardown blocks in VB6 error handling. The discussion in this question is also worth a look.
There's clear and simple way to reset error status - use keyword Resume. There are three possibilities:
Resume
Resume Next
Resume <Label>
Resume continues execution at errored line, Resume Next at next line and least talked Resume Label continues at label. Very useful to create try-catch-finally like constructs in VB6. Borrowed and modified from OneNerd answer:
Function MyFunction() as String
'-- start of error block
'
On Error Goto Catch
' do something here that might cause an error
MyFunction = "IT WORKED"
Goto Finally
Catch:
' error occured - do something else
MyFunction = Err.Description
Err.Clear
Resume Finally ''added to clear error status
Finally:
On Error Resume Next ''added to avoid repeated errors
' put your finally code here
'
'-- end of error block
End Function
Simple Err.Clear doesn't help, if some subsequential error occurs in Finally block; Resume Finally does reset internal error state though.
There is a handy right-click menu that lets you turn error handling on and off. Just right-click on a code window and select Toggle, then you can choose "Break on all errors". This will have the effect of disabling all your "On Error" statements.
Here is what I do:
First turn on error handling like this if necessary in your Sub Main() or Sub Form_Load() Sub:
'-- turn on error handling
'
On Error GoTo 0
'
'-------------------------
Now errors will be turned on.
Next, Use the On Error Resume Next and On Error GoTo {label} commands in combination with the Err object. Here is an example of emulating a try/catch/finally:
Function MyFunction() as String
'-- start of error block
'
On Error Goto Catch
' do something here that might cause an error
MyFunction = "IT WORKED"
Goto Finally
Catch:
' error occured - do something else
MyFunction = Err.Description
Err.Clear
Finally:
' put your finally code here
'
'-- end of error block
End Function
/Tools/Options/General/Error Handling
on error goto 0
Should be what you want... It should cause the error to the thrown, and in turn probably unwind up to the RTL...
It's been a long time, but I'm pretty sure that's what you want.
on error resume next
will just continue to the next statement, so you NEED to have plenty of
if err.Number <> 0 then
statements in your code where errors CAN occur...
Have to agree with LarryF, On Error Goto 0 should turn off explicit error-handling that has been turned on by On Error Resume Next. Functions and subroutines do have their own scope for this though. From Dr. Scripto at Microsoft:
Putting On Error Resume Next at the
beginning of the script, as we often
do, makes it apply to the entire body
of the script. But, as we'll see in
later examples, its scope does not
include functions or subroutines. If
you want to handle errors within a
function or subroutine, you must also
include On Error Resume Next in each
of them before checking the Err
object.
You can turn error-handling off with
On Error GoTo 0. So it's possible to
turn error-handling on with On Error
Resume Next just before you want to
check the Err object, and turn it off
after with On Error GoTo 0.
There is no "On Error GoTo -1" so I have no idea where you got that.
VB6 exception handling is covered very thoroughly in the manual.