On Error Resume的速度影响接下来

时间:2014-02-20 08:15:49

标签: vbscript

鉴于vbscript没有与On Error Goto MyLabel一样的vba语法,我正在考虑使用以下方法来处理错误:

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

'...

我的问题是:这种技术对速度的影响是什么?

此外,我想知道是否有更好的方法可以将一些错误处理构建到vbscript

2 个答案:

答案 0 :(得分:2)

  1. 比较正确实施与错误实施的速度是没有意义的。如果您的脚本没有填写其规范而没有错误处理,并且在使用OERN时速度很慢,则必须选择其他语言。
  2. 由于OERN 隐藏错误,其范围应尽可能小。您的示例代码闻起来像是在全球使用OERN - 这是一个非常糟糕的主意。另外:在每次冒险操作和相应的Err.Number检查之后,你需要一个Err.Clear或“On Error GoTo 0”。
  3. 在其他语言中(例如Python)"it's easier to ask forgiveness than permission";由于VBScript的错误处理性质较差,在大多数情况下你应该“先看看”,并且只有在绝对不可避免时才使用OERN(例如检查是否存在注册表项,处理可能失败的外部资源)。
  4. 本地错误处理的习惯用语:

    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
    

    如果您的规范需要进行全局错误处理:

    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
    

    更新评论:

    为什么全球OERN邪恶?考虑:

    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:您添加的Err.Clear位置错误 - 您在错误信息之前错过可以处理错误。

    更新评论II:

    考虑这个演示脚本:

    ' 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
    

    的输出

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

    由于没有Sub saveTheWorld,您只是进行了错误处理,VBScript以及其他所有内容都已过时。你甚至不能再承诺永远不再使用邪恶的全球OERN了,因为你 - 以及那些习惯性地使用它的脚本家伙(从而证明他们的笑话,而不是他们的代码)已经消失了。我们希望调用进程不会将ERRORLEVEL值作为进一步删除的许可证。

    的输出

    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!
    

    展示“先跳过你”的策略。

    良好案例的输出:

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

    显示两条消息(正确地说是这样)。

    现在完全不同了:

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

    请标记缺少第二条消息。除以零将导致在活动OERN范围中执行下一行(保存在gaErr中)并且继续盲目地/盲目地继续。然后检查危险操作(执行main()及其所有子操作)(通过gaErr代理)。这符合规则“在OERN范围内不超过两行(冒险操作和保存错误信息)”。

    为这种全局错误处理付出的代价:您丢失了行号信息 - 优雅地处理错误变得更加困难。

    但是由于你的脚本中只有一个OERN(从现在开始你的程序中不会有Sub caTastrophy()),你可以在开发和调试过程中对它进行注释。

    OERN的输出评论说:

    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
    

答案 1 :(得分:0)

当我在Vbscript中使用错误处理时,我发现它没有性能问题。但是在我的程序中,它通常会做一些非常简单的事情,例如将“失败”语句输出到日志文件然后wscript.quit,所以我从未发现它会降低系统性能。在您提供的示例中,通常会在检查错误的最后On Error Goto 0之后添加End If。这可能导致错误无法清除,因此当您下次执行错误检查时,它仍然错误地存储了旧的错误值。