Error Handling In Vbscript Part Two
Contents |
LippertAugust 23, 20047 0 0 0
The way VBScript implements the error semantics I mentioned last time is sort of interesting. Today I'll talk a bit about the implementation details, and then next time I'll finish up by talkingVbscript On Error Goto
about some philosophy of error handling.
Before I go on, if you haven't vbscript error handling best practices already, read my recent post Spot The Defect to see how IDispatch returns error information in an EXCEPINFO. OK, so we knowError Handling In Vbscript Tutorial
that when an error occurs we are going to have at the very least an HRESULT, and possibly some additional information -- strings describing the error, and so on. When VBScript's IDispatch caller gets an error it records vbscript on error exit a copy of the error in an internal buffer and returns a special error code, SCRIPT_E_RECORDED. That way the script engine knows to not attempt to record the error again, but rather to look at the recorded buffer state when it needs information about the real error. Script engine users should never see this error number. You'll only see it if you're watching EAX in the debugger during a script error.
Note that both On vbscript error handling line number Error statements clear the recorded error information buffer. Once the error winds its way back to the interpreter, the interpreter does a long jump to an error handling routine which saves off additional information that the interpreter knows. For instance, what is the name of the last-accessed variable -- because some error messages include information like that. The interpreter then checks to see if we're in ‘resume next' mode, in which case it cleans up the stack, moves the instruction pointer to the next beginning-of-statement marker, and restarts the interpreter. There is some additional goo that happens in here to make script debugging scenarios work. I won't go into that -- a discussion of all the ways that script errors and the debugger interact would be lengthy indeed. There is also code to handle weird scenarios -- like, a JScript block with a try-catch calls a VBScript block which calls a JScript block, which throws an exception -- but I won't go into those either. If the engine is not in ‘resume next' mode then it reports the error to the host, and returns another special code, SCRIPT_E_REPORTED. This error indicates to the host that an error occurred but that the host already knows about it. This is intended to forestall this problem: suppose you have a JScript block that calls a VBScript block which cLippertAugust 19, 200419 0 0 0 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
On Error Resume Next Vbscript W3schools
talk about it a bit for the next few days. Today, I vbscript error message want to very carefully describe what the error handling semantics are in the language, because there is some
Vbscript Goto
confusion over how exactly it works. There are two statements that affect error handling in VBScript: On Error Resume NextOn Error Goto 0 The meaning of the first seems clear https://blogs.msdn.microsoft.com/ericlippert/2004/08/23/error-handling-in-vbscript-part-two/ -- 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 https://blogs.msdn.microsoft.com/ericlippert/2004/08/19/error-handling-in-vbscript-part-one/ 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 = 5Print "Global code start"Blah1Print "Global code end"Sub Blah1() On Error Resume Next Print "Blah1 Start" Blah2 Print "Blah1 End"End SubSub Blah2() Print "Blah2 Start" Err.Raise InvalidCall Print "Blah2 End"End Sub This prints out Global code startBlah1 StartBlah2 StartBlah1 EndGlobal 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
errors and how they are recorded in Err. Errors can be raised by the interpreter itself (and examples of these are the Subscript out of range and http://blog.ellisons.org.uk/article-2 Division by zero errors above), but the main power of scripting is its use as an integration vehicle for COM components such as ASDI, and many of the errors that need to be handled will originate in such components. When an error occurs the interpreter is going to get an HRESULT, and possibly some additional context information — strings describing the error, and so on, and as error handling it uses the standard programmatic interface to COM by calling IDispatch and therefore errors are returned in an EXCEPINFO structure. (This design dates back to the earliest days of COM; sorry.) Making sense of those error numbers requires some delving into the depths of how COM represents errors — the HRESULT, which is a 32 bit unsigned integer where the high bit indicates whether it is an error error handling in or a success. The remaining bits in the high word indicate the "facility" of the error -- into what broad category does this error fall? The low word indicates the specific error for that facility. HRESULTS are therefore usually talked about in hex, as the bit structure is a lot easier to read in hex! Consider 0x80070013, for example. The high bit is set, so this is an error. The facility code is 7 and the error code is 0x0013 = 19 in decimal. Some common facility codes are listed in Table 1 and Table 2 below. Once the error winds its way back to the interpreter, the interpreter does a long jump to an error handling routine which saves off additional information that the interpreter knows. For instance, what is the name of the last-accessed variable -- because some error messages include information like that. The interpreter then checks to see if we're in 'resume next' mode, in which case it cleans up the stack, moves the instruction pointer to the next beginning-of-statement marker, and restarts the interpreter. There is some additional goo that happens in here to make script debugging scenarios work. I won't go into that &mda