如何在VB6的错误处理程序中处理错误?

4
我经常在我的VB6应用程序中遇到这种情况。
Private Sub DoSomething

  On Error Goto err1

  Call ProcessLargeBatch1
  Call ProcessLargeBatch2
  '... more ...'

  Exit Sub

err1:
  Call Cleanup 'Specific for DoSomething'
  Call HandleError 'General error handling: Logging, message box, ...'

End Sub

清理过程有时会还原操作、回滚事务、删除临时文件等。在大多数情况下,此操作也可能失败。

在这种情况下我该怎么办?我可以在错误处理程序中添加 On Error Resume Next 但这将删除现有的 Err 对象。将错误处理程序添加到 Cleanup 也有同样的问题。

保证原始错误仍然得到处理/记录的最佳方式是什么?

编辑:另外一个问题是我想通知用户发生了错误。有时很重要清理快速完成,并且不希望消息框长时间阻塞应用程序,只有用户确认错误后才执行清理。

5个回答

4

首先,读取Err对象中所有需要的信息,例如编号、描述等,然后清除错误并执行你想要的操作。

改变向用户提供信息的方式,使用已缓存的值而不是直接使用Err对象。


3
从你的例子来看,你正确地进行了清理。你的HandleError应该只记录错误而不涉及任何UI。UI是在表单级别上处理的。
当发生错误时,你需要做的是:
1. 清理 2. 记录错误 3. 通过Err.Raise再次引发错误
这将沿着调用堆栈工作到调用原始代码的事件。然后,顺序将变为:
1. 清理 2. 记录错误 3. 显示错误通知对话框
请注意,你的错误日志记录可以很智能,因为相同错误的后续日志只需添加到记录的调用堆栈中。
你要确保每个事件都有一个错误处理程序。并非每个过程都需要一个,但是每个事件肯定需要一个。在事件中未处理的错误会导致VB6应用程序意外关闭。

虽然这并没有直接帮助到你的建议,但它确实产生了惊人的效果!现在我拥有了更加复杂和健壮的错误处理机制,包括(伪)堆栈跟踪。(你没有提到缓存 Err 对象,这是我的原始问题的解决方案,因此我接受了 Patrick 的答案) - Daniel Rikowski

2
如果我可以在一个地方处理所有的错误,我通常会把它放到一个类似于这样的结构中:
Public Sub SubThatShouldHandleErrors()
Const ROUTINE_NAME = "SubThatShouldHandleErrors"
On Error Goto Catch

    ' "normal" processing here...

Finally:
    ' non-error case falls through to here
    ' perform clean-up that must happen even when an error occurred
    On Error Goto 0 ' reset: not really needed any more, but it makes me feel more comfortable
    Exit Sub

Catch:
    ' Error handling here, I may have logging that uses ROUTINE_NAME
    Resume Finally

End Sub

如果我需要多个错误处理程序,我会尽力重构我的代码,使其不再需要,但如果绝对必要,我会编写自定义处理程序;我的模板只是一个指导方针。


1

首先记录您的错误。然后执行 On Error Resume Next。将清理工作封装在具有自己错误处理的方法中。这应该是您最好的选择。


谢谢。不幸的是,那并不能总是帮助我。我已经在我的问题中添加了解释。 - Daniel Rikowski

0

我真的真的不喜欢错误处理程序。这是我的做法:

  • 创建一个Error类或模块,其中包含内置类包含的所有属性,以及一个CopyError方法,从err对象中填充这些属性。
  • 注意可能出现错误的位置:

.

' lots of code that will probably work
On Error Resume Next
Open "c:\filethatdoesntexist.txt" For Input As #1
Error.CopyError
On Error Goto 0
Select Case Error.Number
    Case 53'File doesn't exist
        ' handle that error here
    Case 0
        ' no error
    Case Else
        ' Just throw the error on
        Err.Raise Error.Number, Error.Description, ...
End Select
' more code that will probably work

一个小的改进:你可以用 Error 类中的 Raise 方法替换 Err.Raise... 行,以节省一些打字。 - Mike Spross

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