Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
368 views
in Technique[技术] by (71.8m points)

vbscript - Speed impact of On Error Resume Next

Given that vbscript does not have the On Error Goto MyLabel kind of syntax as with vba, I'm considering using the following to handle errors:

On Error Resume Next

'Do some stuff

If Err.Number <> 0 Then
    Err.Clear
    'Handle the error
End If

'Do some more stuff

If Err.Number <> 0 Then
    Err.Clear
    'Handle the error
End If

'...

My question is: What would the speed impact be of this type of technique?

Additionally, I would like to know if there is a better way to build some error handling into vbscript

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
  1. It makes no sense to compare the speed of a correct vs. a faulty implementation. If your script does not fullfill its specs without error handling and is to slow when using OERN, you have to choose another language.
  2. As OERN hides errors, its scope should be as small as possible. Your sample code smells like using OERN globally - a very bad idea. In addition: You need a Err.Clear or "On Error GoTo 0" after each risky operation and its corresponding check of Err.Number.
  3. In other languages (e.g. Python) "it's easier to ask forgiveness than permission"; because of the poor nature of VBScript's error handling you should "look before you leap" in most cases and use OERN only when absolutely unavoidable (e.g. check for existence of registry keys, deal with possibly failing external resources).

The idiom for local error handling:

Dim gaErr ' global error array
...
Sub SomeSub()
    ...
    OERN
    risky op
    gaErr = Array(Err.Number, Err.Description, ...)
    OEG0
    If gaErr(0) Then
       handle error
    ...
End Sub

If your specs make a global error handling necessary:

Dim gaErr
OERN
ret = main()
gaErr = Array(...)
OEG0
If gaErr(0) Then
   some fatal/not locally handled error occured somewhere in your script
   handle it gracefully
Else
   If ret is bad Then
      deal with this
   Else
      ask for more money
   End If
End If
WScript.Quit good/bad

Function main()
  main = ...
End Function

Update wrt comment:

Why is a global OERN evil? Consider:

OERN
(1) Process/change important data
(2) Delete original data - if (1) failed you just destroyed the base of your business

OERN
(1) Process/change important data
(2) If Err.Nunber Then Backup(database, destinatiom)
(3) Continue although the Backup didn't take place, because at least three error were hidden

BTW: Your addition of the Err.Clear are in the wrong place - you loose the error info before you can handle the error.

Update wrt comment II:

Consider this demo script:

' dgeh.vbs - demo global error handling

Option Explicit

' globals
Dim gWAN : Set gWAN = WScript.Arguments.Named
Dim gaErr

Dim iRet
' top-level/global OERN starts here (errors before will abort mercylessly)
On Error Resume Next
 iRet  = main() ' not more than two statements!
 gaErr = Array(Err.Number, Err.Description, Err.Source)
On Error GoTo 0
If gaErr(0) Then
   WScript.Echo "Fatal Error:", Join(gaErr, " * ")
   iRet = 1 ' or choose a better number
Else
   If iRet Then
      WScript.Echo "need one of /good, /bad, or /fatal, Mr. User!"
   Else
      WScript.Echo "all's well"
   End If
End If
WScript.Quit iRet

Function main()
  main = 2
  If gWAN.Count = 1 And (gWAN.Exists("good") Or gWAN.Exists("bad") Or gWAN.Exists("fatal")) Then
     readTheDocs
     main = 0
  End If
End Function

Sub readTheDocs()
    WScript.Echo "read Microsoft's Docs"
    If gWAN.Exists("fatal") Then
       caTastrophy
    Else
       trySomethingRisky
    End If
End Sub

Sub trySomethingRisky()
  Dim n
  If gWAN.Exists("bad") Then n = 1 / 0
  WScript.Echo "but be skeptical of the text and your interpretation"
End Sub

Sub caTastrophy()
  On Error Resume Next ' simulating the evil global OERN and not checking *each* statement
     WScript.Echo "saving the world"
     saveTheWorld
     WScript.Echo "deleting the now obsolete original"
  On Error GoTo 0
End Sub

output for

cscript dgeh.vbs /fatal
read Microsoft's Docs
saving the world
deleting the now obsolete original
all's well
echo %ERRORLEVEL%
0

As there is no Sub saveTheWorld, you just made error handling, VBScript, and all the rest obsolete. You can't even promise never to use the evil global OERN again, because you - and those scripting guys who use it habitually (and thereby have proven that they are paid for their jokes, not their code) - have vanished. Let's hope the calling process won't take the ERRORLEVEL value as licence for some further deletions.

output for

cscript dgeh.vbs
need one of /good, /bad, or /fatal, Mr. User!
echo %ERRORLEVEL%
2

cscript dgeh.vbs /nix
need one of /good, /bad, or /fatal, Mr. User!

cscript dgeh.vbs /fatal /bad
need one of /good, /bad, or /fatal, Mr. User!

demonstrate the "look before you jump" strategy.

output for the good case:

cscript dgeh.vbs /good
read Microsoft's Docs
but be skeptical of the text and your interpretation
all's well
echo %ERRORLEVEL%
0

both messages are shown (and rightfully so).

and now something entirely different:

cscript dgeh.vbs /bad
read Microsoft's Docs
Fatal Error: 11 * Division by zero * Microsoft VBScript runtime error
echo %ERRORLEVEL%
1

Please mark the absence of the second message. The divide by zero will cause the execution of the next line in the active OERN scope (saving in gaErr) and not continue blindly/mindlessly. The risky operation (doing what main() and all its children do) is then checked (via the gaErr proxy). That honors the rule "no more than two line (risky op and saving the eror info) in an OERN scope".

The price to pay for this kind of global error handling: You loose the line number info - dealing gracefully with an error becomes more difficult.

But as there is just one OERN in your script (you won't have Sub caTastrophy() in your programs from now on), you can comment it out during development and debugging.

output with OERN commented out:

cscript dgeh.vbs /bad
read Microsoft's Docs
E:rialsSoTrialsanswers21901890vbsdgeh.vbs(46, 30) Microsoft VBScript runtime error: Division by zero

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...