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

如何在VB6中处理错误处理程序中的错误?,vb6,error-handling,Vb6,Error Handling,我在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, m

我在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
也有相同的问题

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


编辑:另一个问题是我还想通知用户错误。有时,清理速度要快,我不希望消息框长时间阻止应用程序,在用户确认错误后进行清理,这一点很重要。

首先记录错误。然后在下一步执行错误恢复。将清理封装在具有自己的错误处理的方法中。这应该是你最好的选择。

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

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


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


更改通知用户使用缓存的值的方式,不要使用Err对象本身。

如果我可以在一个位置处理所有错误,我通常会将其放入如下结构中:

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

如果我需要一个以上的错误处理程序,我会尽力重新构造我的代码,使其不会出现这种情况,但如果绝对必要,我会编写一个自定义处理程序;我的模板只是一个指南。

根据您的示例,您正在正确地进行清理。您的HandleError应该只记录错误,而不记录任何UI。UI是在表单级别处理的

发生错误时,您需要做的是

  • 清理
  • 记录错误
  • 通过Err.Raise再次引发错误
  • 这将在调用堆栈上一直运行到调用原始代码的事件。然后序列将变为

  • 清理
  • 记录错误
  • 显示“错误通知”对话框
  • 请注意,错误日志可以是智能的,因为相同错误的后续日志可以添加到记录的调用堆栈中


    您希望确保每个事件都有一个错误处理程序。不是每个程序都需要一个,但肯定是每个事件。事件中未经处理的错误将导致VB6应用程序意外关闭

    多谢各位。不幸的是,这并不总是对我有帮助。我对我的问题加了一个解释。虽然这对你的建议没有什么帮助,但它还是产生了奇迹!我现在有了更复杂、更健壮的错误处理,包括(伪)堆栈跟踪。(您没有提到缓存Err对象,这是我最初问题的解决方案,因此我接受了Patrick的回答)一个小的改进:您可以在
    Error
    类中使用
    Raise
    方法替换
    Err.Raise…
    行,该方法执行相同的操作,以进行相同的键入。
    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