Speed impact of On Error Resume Next

后端 未结 2 1960
暗喜
暗喜 2020-12-12 05:31

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

相关标签:
2条回答
  • 2020-12-12 06:16

    When i use error handling in Vbscript i do not find it has a performance issue. However in my programs it will normally do something quite simple like output a "Failed" statement to a log file then wscript.quit, so i have never found it to reduce system performance. On the example you have given it is usual to add a On Error Goto 0 after the last End If where you are checking for an error. This could cause an error not to be cleared so when you next perform an error check it has incorrectly still storing the old error value.

    0 讨论(0)
  • 2020-12-12 06:17
    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:\trials\SoTrials\answers\21901890\vbs\dgeh.vbs(46, 30) Microsoft VBScript runtime error: Division by zero
    
    0 讨论(0)
提交回复
热议问题