Fabulous Adventures In Coding

Eric Lippert's Blog

Error Handling in VBScript, Part One

OK, enough about the Peloponnesian war -- a number of readers have asked me questions about error handling in VBScript recently, so I think I'll talk about it a bit for the next few days.

Today, I want to very carefully describe what the error handling semantics are in the language, because there is some confusion over how exactly it works. There are two statements that affect error handling in VBScript:

On Error Resume Next
On Error Goto 0

The meaning of the first seems clear -- if you get an error, ignore it and resume execution on the next statement. But as we'll see, there are some subtleties. But before that, what the heck is up with the second statement?

The second statement turns off 'resume next' mode if it is on. Yes, the syntax is ridiculous -- something like On Error Raise would be a whole lot more clear. But for historical purposes, this is what we're stuck with. Visual Basic has an error handling mode which VBScript does not -- VB can branch to a labeled or numbered statement. (Remember line numbers? Those were the days!) To tell VB that you no longer wish to branch to that statement, you give zero, an invalid line number. C'est super-beaucoup-de-fromage, n'est-ce pas? But we're stuck with it now.

The subtlety in the "resume next" mode is best illustrated with an example.

Const InvalidCall = 5
Print "Global code start"
Blah1
Print "Global code end"
Sub Blah1()
      On Error Resume Next
      Print "Blah1 Start"
      Blah2
      Print "Blah1 End"
End Sub
Sub Blah2()
      Print "Blah2 Start"      
      Err.Raise InvalidCall
      Print "Blah2 End"
End Sub

This prints out

Global code start
Blah1 Start
Blah2 Start
Blah1 End
Global code end

Hold on a minute -- when the error happened, Blah1 had already turned 'resume next' mode on. The next statement after the error raise is Print "Blah2 End" but that statement never got executed. What's going on?

What's going on is that the error mode is on a per-procedure basis, not a global basis. (If it were on a global basis, all kinds of bad things could happen -- think about how you'd have to design a program to have consistent error handling in a world where that setting is global, and you'll see why it's per-procedure.) In this case, Blah2 gets an error. Blah2 is not in 'resume next' mode, so it aborts itself, records that there was an error situation, and returns to its caller. The caller sees the error, but the caller is in 'resume next' mode, so it resumes.

In short, the propagation model for errors in VBScript is basically the same as traditional structured exception handling -- the exception is thrown up the stack until someone catches it, or the program terminates. However, the error information that can be thrown, and the semantics of the catcher are quite a bit weaker than, say, JScript's structured exception handling.

Also, remember that the 'next' in 'resume next' mode is the next statement. Consider these two programs, for example. Do they have the same semantics?

On Error Resume Next
Temp = CInt(Foo.Bar(123))
Blah Temp
Print "Done"

On Error Resume Next
Blah CInt(Foo.Bar(123))
Print "Done"

No! If Foo.Bar raises an error, then the first one passes Empty to Blah. The second one never calls Blah at all if an error is raised, because it resumes to the next statement.

You can get into similar trouble with other constructs. For example, these do have the same semantics:

On Error Resume Next
If Blah Then
      Print "Hello"
End If
Print "goodbye"

On Error Resume Next
If Blah Then Print "Hello"
Print "goodbye"

If Blah raises an error then it resumes on the Print "Hello" in either case. You can also get into trouble with loops:

On Error Resume Next
For index = 1 to Blah
      Print TypeName(index)
Next
Print "Goodbye"

If Blah raises an error, this resumes into the loop, not after the loop. This prints out

Empty
Goodbye

Be careful! Next time I'll talk a bit about ways to avoid these gotchas, the semantics of the Err object, and general philosophies of error handling.

Published Thursday, August 19, 2004 11:14 AM by Eric Lippert
Filed under: ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

 

Jiho Han said:

Fantabulous!
Keep it up!
August 19, 2004 12:18 PM
 

John S. said:

Ditto!
August 19, 2004 12:44 PM
 

Fabulous Adventures In Coding said:

August 23, 2004 1:41 PM
 

David Candy said:

One thing I've learnt is not to be too clever on a line. Because If I get it wrong I have to change it to multiline to see what function is freaking. In the above is blah, CInt, or Foo.Bar not working. Also I never use

If expression then

but If expression = true then
September 2, 2004 10:07 PM
 

Fabulous Adventures In Coding said:

September 9, 2004 1:13 PM
 

Benjohn said:

Thanks - that's the only useful explaination I've read.

October 29, 2007 11:56 AM
 

Alex French said:

This is probably the best explanation I've seen so far.

Everything I read about VBScript going back a few years said it was impossible to swith the error handling off after an On Error Resume Next in VBScript (but not VB) but this seems to contradict this...

Thanks

December 11, 2007 3:38 AM
 

Eric Lippert said:

I suppose that "everything" did not include the documentation. :-)  

(http://msdn2.microsoft.com/en-us/library/53f3k80h.aspx

That's probably where you should have started.

December 11, 2007 11:07 AM
 

Jayasimha said:

Hi,

Very good explanation.

Thanks

Regards

Jayasimha

January 18, 2008 12:12 PM
 

Kunals said:

Nice work helps a lot in understanding.

February 12, 2008 3:00 AM
 

Ivan Bessolitsyn said:

It's ok but where is the "Next time I'll talk a bit about ways to avoid these gotchas..."  - there is nothing in next chapters about how to work with Blah if "IF...ELSE" block is bigger that one string... except "Use the right tool for the job". Is there any solution?

Thanx,

Ivan B.

December 9, 2008 10:14 AM
 

Swati said:

Good Explanation!!!!!!!!!!!!!!

December 17, 2008 11:26 PM
 

Kc said:

Explanation is Good and it is easy to understand.

January 22, 2009 9:09 AM
 

Chandan said:

How do i go to the next part of the topic?

March 25, 2009 5:23 AM
 

Andy said:

March 30, 2009 8:32 AM

Leave a Comment

(required) 
(optional)
(required) 
Submit

About Eric Lippert

Eric Lippert is a senior developer on the Microsoft C# compiler team. Before that he worked on the framework of Visual Studio Tools For Office. Before that, he worked on the compilers, runtimes and tools for VBScript, JScript, Windows Script Host and other Microsoft Scripting technologies. He lives in Seattle and spends his free time editing books about programming languages, playing the piano, and trying to keep his tiny sailboat upright in Puget Sound.

This Blog

Syndication


© 2009 Microsoft Corporation. All rights reserved. Terms of Use  |  Trademarks  |  Privacy Statement
Microsoft
Page view tracker