在VBScript中,Try-Catch-End Try似乎无法正常工作

43
我正在尝试以下代码:

Try ' DOESN'T WORK
    Throw 2 ' How do I throw an exception?
Catch ex
    'What do I do here?
End Try

但是我在catch子句中遇到了错误Statement expected

有人知道如何在VBScript中使用try/catch来捕获/抛出异常吗?(我不想使用On Error Do X的解决方案。)


4
那么你会非常失望。在早期的VB版本中(包括VB 6、VBA和VBScript),没有Try-Catch支持。如果你知道如何正确使用,On Error Resume Next并不那么糟糕。 - Cody Gray
以下是有关正确使用它的一些提示! :-) - Mark
4个回答

81

处理错误

在VBScript中,我们可以使用一种“旧式”的错误处理方式,它确实使用了On Error Resume Next。首先我们启用它(通常放在文件的顶部;但你也可以在第一个Err.Clear的位置使用它,以实现它们的联合效果),然后在运行可能产生错误的代码之前清除已经发生过的任何错误,运行可能产生错误的代码,最后明确检查是否有错误:

On Error Resume Next
' ...
' Other Code Here (that may have raised an Error)
' ...
Err.Clear      ' Clear any possible Error that previous code raised
Set myObj = CreateObject("SomeKindOfClassThatDoesNotExist")
If Err.Number <> 0 Then
    WScript.Echo "Error: " & Err.Number
    WScript.Echo "Error (Hex): " & Hex(Err.Number)
    WScript.Echo "Source: " &  Err.Source
    WScript.Echo "Description: " &  Err.Description
    Err.Clear             ' Clear the Error
End If
On Error Goto 0           ' Don't resume on Error
WScript.Echo "This text will always print."

上面的代码仅在发生错误时打印出错误信息。如果该错误导致脚本无法执行,您可以将第二个Err.clear替换为WScript.Quit(Err.Number)
还请注意On Error Goto 0,它会在发生错误时关闭在下一条语句处恢复执行的操作。
如果您想测试Set成功的情况,可以注释掉那行代码,或创建一个将成功的对象,例如vbscript.regexpOn Error指令仅影响当前运行范围(当前的SubFunction),不会影响调用或被调用的范围。

引发错误

如果要检查某种状态,然后引发由调用您的函数处理的错误,则可以使用Err.RaiseErr.Raise最多需要五个参数:NumberSourceDescriptionHelpFileHelpContext。 使用帮助文件和上下文超出了本文的范围。 Number是您选择的错误号码,Source是引发错误的应用程序/类/对象/属性的名称,Description是发生的错误的简短描述。
If MyValue <> 42 Then
    Err.Raise(42, "HitchhikerMatrix", "There is no spoon!")
End If

如上所述,您可以处理引发的错误。


更改日志

  • 编辑#1: 在可能导致错误的行之前添加Err.Clear以清除任何先前被忽略的错误。
  • 编辑#2: 澄清。
  • 编辑#3: 在代码块中添加了注释。澄清了在On Error Resume NextErr.Clear之间预计会有更多代码。修正了一些语法问题,使其更不拘泥于形式。增加了关于Err.Raise的信息。格式化。

  • 1
    我更喜欢使用"If Err"而不是"If Err.Number <> 0",但这主要是一种风格偏好。 - Tmdean
    我原本想改变它,但是对我来说,在调用Err.Clear并在之后使用“if not null”样式检查有点奇怪。这完全取决于个人风格偏好。 - Mark
    第一个 Err.Clear 是多余的,因为 On Error Resume Next 会为您重置 Err 对象。此外,不要提到 Err.Raise,它是 VBScript 错误处理工具中非常有用的工具。 - user692942
    @Lankymart 谢谢。我已经澄清了为什么我使用了第一个 Err.Clear。我已经添加了关于 Err.Raise 的信息。 - Mark
    1
    有道理,感谢澄清。关于引发错误的话题,您可能会发现这篇文章很有趣:http://www.4guysfromrolla.com/webtech/021201-1.shtml - user692942

    24

    VBScript没有Try/Catch语句。(VBScript 语言参考。如果有Try语句,它会在语句部分列出。)

    On Error Resume Next 是VBScript中唯一的错误处理方式。很抱歉。 如果你需要使用try/catch,JScript是一个选项。它在所有支持VBScript的地方都得到支持,并具有相同的功能。


    如果它没有Try/Catch,那么为什么在Try上不会出错呢? - user541686
    7
    我猜它应该也支持Trraoysfoaiuerlkj(一串似乎无意义的字母组合),因为如果你把“Try”改成那个词,它也不会出错。 ;) 我猜它认为“Try”可能是之后脚本里的子程序名称。 - Tmdean
    3
    没错,VBScript将其视为没有参数的子程序,因此如果您不使用Option Explicit或使用On Error Resume Next,则不会出现错误。这就是为什么您应该经常使用Option Explicit并尽量少使用On Error Resume Next的原因。因为如果您犯了一个拼写错误,您可以通过提及未声明的语句或无法识别的子/函数轻松检测到它。 - AutomatedChaos
    哦,我从来不知道Option Explicit在VBScript中也可以使用...我只在VB 6中用过它,谢谢!(我还以为Try是一个关键字,因为Notepad++会将Try和Catch标记出来...:\) - user541686
    4
    我其实在谷歌上搜索了“Trraoysfoaiuerlkj”。谢谢你,天才。 - You_Shall_Not_Pass
    在WSH下,VBScript的事件处理机制比Javascript简单一些。请参见这里 - Zev Spitz

    4

    在VBScript中通过变通方式实现Try Catch

    http://web.archive.org/web/20140221063207/http://my.opera.com/Lee_Harvey/blog/2007/04/21/try-catch-finally-in-vbscript-sure

    Class CFunc1
        Private Sub Class_Initialize
            WScript.Echo "Starting"
            Dim i : i = 65535 ^ 65535 
            MsgBox "Should not see this"
        End Sub
    
        Private Sub CatchErr
            If Err.Number = 0 Then Exit Sub
            Select Case Err.Number
                Case 6 WScript.Echo "Overflow handled!" 
                Case Else WScript.Echo "Unhandled error " & Err.Number & " occurred."
            End Select
            Err.Clear
        End Sub
    
        Private Sub Class_Terminate
            CatchErr
            WScript.Echo "Exiting" 
        End Sub 
    End Class
    
    Dim Func1 : Set Func1 = New CFunc1 : Set Func1 = Nothing
    

    8
    虽然这种写法有点酷,从巧妙的角度来看,但“巧妙”的代码往往难以阅读和维护/使用。我不太愿意对此进行评分降级,但实际用于生产目的时,这确实是“糟糕的代码”。虽然在学术上很酷。 - Mark

    0

    有时候,特别是在使用VB时,你可能会错过一些显而易见的解决方案。就像我在过去两天里所做的那样。

    生成错误的代码需要移动到一个单独的函数中。在函数的开头写上On Error Resume Next。这样可以“吞噬”错误,而不会吞噬其他错误。将代码分成小的独立函数也可以提高可读性、重构和添加新功能更容易。


    1
    或者你可以在生成错误的代码之后加上 On Error Goto 0,这样你就不会产生函数调用的开销(也不需要那些不做任何实际工作的小函数)。 - Mark

    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接