On Error 语句 (Visual Basic)

启用错误处理例程,并指定例程在过程中的位置;还可用于禁用错误处理例程。 On Error 语句在非结构化错误处理中使用,可用于替代结构化异常处理。 结构化异常处理内置在 .NET 中,通常更加高效,因此在应用程序中处理运行时错误时建议采用这种处理。

如果不进行错误处理或异常处理,则发生的任何运行时错误都是严重错误:会显示错误消息并停止执行。

注意

Error 关键字也可在 Error 语句中使用,支持这种做法是为了实现后向兼容性。

语法

On Error { GoTo [ line | 0 | -1 ] | Resume Next }

组成部分

术语 定义
GoToline 启用从必需 line 参数中所指定的行开始的错误处理例程。 line 参数是任何行标签或行号。 如果发生运行时错误,则控制会转移到指定行,从而使错误处理程序处于活动状态。 指定行必须与 On Error 语句处于同一过程中,否则会发生编译时错误。
GoTo 0 在当前过程中禁用已启用的错误处理程序,并将它重置为 Nothing
GoTo -1 在当前过程中禁用已启用的异常,并将它重置为 Nothing
Resume Next 指定在发生运行时错误时,控件会转到紧跟在发生错误的语句后的语句,执行会从该点继续进行。 访问对象时使用此形式,而不是 On Error GoTo

注解

注意

建议尽可能在代码中使用结构化异常处理,而不是使用非结构化异常处理和 On Error 语句。 有关详细信息,请参阅 Try...Catch...Finally 语句

“已启用”错误处理程序是由 On Error 语句开启的处理程序。 “活动”错误处理程序是正在处理错误的已启用处理程序。

如果在错误处理程序处于活动状态时(介于错误发生与 ResumeExit SubExit FunctionExit Property 语句之间)发生某个错误,则当前过程的错误处理程序无法处理该错误。 控制会返回到调用过程。

如果调用过程具有已启用错误处理程序,则会激活它以处理错误。 如果调用过程的错误处理程序也处于活动状态,则控制会沿着以前的调用过程向回传递,直到找到已启用但非活动的错误处理程序。 如果未找到此类错误处理程序,则在实际发生错误的位置处,错误是严重错误。

每次错误处理程序将控制传递回某个调用过程时,该过程会成为当前过程。 错误由任何过程中的错误处理程序进行处理后,执行会在当前过程中由 Resume 语句指定的位置处继续进行。

注意

错误处理例程不是 Sub 过程或 Function 过程。 它是由行标签或行号标记的代码部分。

Number 属性

错误处理例程依赖于 Err 对象的 Number 属性中的值来确定错误的原因。 例程应先测试或保存 Err 对象中的相关属性值,然后才能发生任何其他错误或调用可能导致错误的过程。 Err 对象中的属性值仅反映最近的错误。 与 Err.Number 关联的错误消息包含在 Err.Description 中。

Throw 语句

使用 Err.Raise 方法引发的错误会将 Exception 属性设置为 Exception 类的新创建实例。 为了支持引发派生异常类型的异常,语言中支持 Throw 语句。 此语句采用单个参数,该参数是要引发的异常实例。 下面的示例演示如何将这些功能与现有异常处理支持一起使用:

    On Error GoTo Handler
    Throw New DivideByZeroException()
Handler:
    If (TypeOf Err.GetException() Is DivideByZeroException) Then
    ' Code for handling the error is entered here.
    End If

请注意,On Error GoTo 语句会捕获所有错误,而不考虑异常类。

On Error Resume Next

On Error Resume Next 会使执行继续运行紧跟在导致运行时错误的语句后的语句,或是继续运行紧跟在包含 On Error Resume Next 语句的过程的最近一次调用后的语句。 此语句允许在出现运行时错误的情况下继续执行。 可以将错误处理例程放置在发生错误的位置,而不是将控制转移到过程中的其他位置。 On Error Resume Next 语句会在调用其他过程时变为非活动状态,因此如果希望在该例程中进行内联错误处理,则应在每个调用的例程中执行 On Error Resume Next 语句。

注意

在处理访问其他对象期间生成的错误时,On Error Resume Next 构造可能比 On Error GoTo 更可取。 每次与对象交互后检查 Err 可消除有关代码访问的对象的歧义。 可以确定哪个对象将错误代码置于 Err.Number 中,以及哪个对象最初生成了错误(Err.Source 中指定的对象)。

On Error GoTo 0

On Error GoTo 0 在当前过程中禁用错误处理。 它不会将行 0 指定为错误处理代码的开头,即使过程包含编号为 0 的行。 如果没有 On Error GoTo 0 语句,则退出过程时会自动禁用错误处理程序。

On Error GoTo -1

On Error GoTo -1 在当前过程中禁用异常。 它不会将行 -1 指定为错误处理代码的开头,即使过程包含编号为 -1 的行。 如果没有 On Error GoTo -1 语句,则退出过程时会自动禁用异常。

若要防止错误处理代码在未发生错误时运行,请紧挨在错误处理例程前面放置 Exit SubExit FunctionExit Property 语句,如下面的片段所示:

Public Sub InitializeMatrix(ByVal Var1 As Object, ByVal Var2 As Object)
   On Error GoTo ErrorHandler
   ' Insert code that might generate an error here
   Exit Sub
ErrorHandler:
   ' Insert code to handle the error here
   Resume Next
End Sub

此处,错误处理代码跟踪 Exit Sub 语句后面,并位于 End Sub 语句前面,以将它与过程流分开。 可以将错误处理代码置于过程中的任何位置。

未捕获的错误

当对象作为可执行文件运行时,对象中的未捕获错误会返回到控制应用程序。 在开发环境中,仅当设置了正确选项时,未捕获的错误才会返回到控制应用程序。 有关调试期间应设置的选项、如何设置选项以及主机是否可以创建类的说明,请参阅主机应用程序的文档。

如果创建访问其他对象的对象,应尝试处理它们传递回的任何未经处理的错误。 如果你无法处理,则将 Err.Number 中的错误代码映射到你自己的错误之一,然后将它们传递回对象的调用方。 应通过将错误代码添加到 VbObjectError 常量来指定错误。 例如,如果错误代码为 1052,请按如下所示分配它:

Err.Number = vbObjectError + 1052

注意

调用 Windows动态链接库 (DLL) 期间的系统错误不会引发异常,无法使用 Visual Basic 错误捕获进行捕获。 调用 DLL 函数时,应检查每个返回值是成功还是失败(根据 API 规范),如果失败,则检查 Err 对象的 LastDLLError 属性中的值。

示例

此示例首先使用 On Error GoTo 语句指定错误处理例程在过程中的位置。 在该示例中,尝试除以零会生成错误号 6。 错误在错误处理例程中进行处理,控制随后会返回到导致错误的语句。 On Error GoTo 0 语句会关闭错误捕获。 On Error Resume Next 语句随后用于延迟错误捕获,以便可以确定下一个语句生成的错误的上下文。 请注意,Err.Clear 用于在处理错误后清除 Err 对象的属性。

Public Sub OnErrorDemo()
   On Error GoTo ErrorHandler   ' Enable error-handling routine.
   Dim x As Integer = 32
   Dim y As Integer = 0
   Dim z As Integer
   z = x / y   ' Creates a divide by zero error
   On Error GoTo 0   ' Turn off error trapping.
   On Error Resume Next   ' Defer error trapping.
   z = x / y   ' Creates a divide by zero error again
   If Err.Number = 6 Then
      ' Tell user what happened. Then clear the Err object.
      Dim Msg As String
      Msg = "There was an error attempting to divide by zero!"
      MsgBox(Msg, , "Divide by zero error")
      Err.Clear() ' Clear Err object fields.
   End If
Exit Sub      ' Exit to avoid handler.
ErrorHandler:  ' Error-handling routine.
   Select Case Err.Number   ' Evaluate error number.
      Case 6   ' Divide by zero error
         MsgBox("You attempted to divide by zero!")
         ' Insert code to handle this error
      Case Else
         ' Insert code to handle other situations here...
   End Select
   Resume Next  ' Resume execution at the statement immediately 
                ' following the statement where the error occurred.
End Sub

要求

命名空间:Microsoft.VisualBasic

程序集:Visual Basic 运行时库(在 Microsoft.VisualBasic.dll 中)

另请参阅