我正在研究传统的VB6 exe程序。程序无法再继续存在各种情况。程序不是将错误消息返回给调用者,而是通过消息框显示错误,然后使用End
终止。
有什么方法可以通过最小可能的更改来改变这种行为?
例如,我使用全局字符串变量,我会在使用End
的地方设置此全局变量中的错误而不是显示错误,然后通过使用某些关键字/技术我返回到第一个调用者(而不是使用Exit Sub/Function
时发生的最后一个调用者)
Private Sub Button_Click()
Call DoSomething()
End Sub
Public Sub DoSomething()
Call DoThing_1()
Call DoThing_2()
End Sub
Public Sub DoThing_1()
Call DoThing_A()
...
Call DoThing_B()
...
MsgBox "Error Here"
'End
Exit Sub 'As i have asked(if possible), instead of returning to DoSomething(), the call should return to Button_Click
...
Call DoThing_C()
...
End Sub
答案 0 :(得分:4)
VB中错误管理和恢复的规范方法是使用On Error
语句引发错误并处理(“陷阱”)调用堆栈中其他位置更高的错误。
引发的错误将通过调用堆栈向上移动,直到它遇到具有通过On Error
定义的错误处理程序的函数,或者直到调用堆栈为空,此时程序将终止,错误发生在手。
因此,如果您将End
替换为Err.Raise
(请参阅VBA上的MSDN,因为MS非常谨慎地删除了实际的VB语言参考),您可以这样做:
Option Explicit
' you don't need to, but it's good style to have meaningful error numbers
' (vbObjectError is the error number after which user-defined errors may exist)
Const MY_ERROR_TYPE_A As Integer = vbObjectError + 1
Const MY_ERROR_TYPE_B As Integer = vbObjectError + 2
Public Sub Button_Click()
On Error GoTo Err_Button_Click
Call DoSomething
Exit Sub
Err_Button_Click:
Select Case Err.Number
Case MY_ERROR_TYPE_A:
MsgBox "Error during Button_Click: " & vbNewLine & _
Err.Description & vbNewLine & _
"in " & Err.Source, vbExclamation, "Oops"
Err.Clear
Resume Next
Case MY_ERROR_TYPE_B:
MsgBox Err.Description, vbCritical, "This is really bad."
End
End Select
End Sub
Public Sub DoSomething()
Call DoThing_1
Call DoThing_2
End Sub
Public Sub DoThing_1()
Dim frob
Call DoThing_A
'...
Call DoThing_B
'...
If frob = 0 Then
Err.Raise MY_ERROR_TYPE_A, "DoThing_1", "Could not frob the buzz"
End If
'...
Call DoThing_C
'...
End Sub
你可以看到工作的主要内容是在“第一个来电者”功能中完成的。但是,您仍然必须在整个代码中识别它们,并为它们添加适当的错误处理块。您至少在每个事件处理程序中都需要进行错误处理。
这里Button_Click
定义了一个错误处理程序。通常,这是一个只能通过某个标签访问的代码块,即前面有一个Exit Sub
/ Exit Function
,您需要GoTo
才能到达那里。在该块中,您可以向用户显示有意义的消息,并通过Resume Next
继续执行程序,或者结束程序,具体取决于您正在查看的错误。
它不必像上面的样本那样精细。你可以实现它的最小版本 - 没有错误常量,没有消息,只有Err.Raise
和On Error
,但是投入更多努力最终可能会变得有用,特别是在程序中到目前为止没有任何错误处理。
答案 1 :(得分:0)
我在这里多次遵循的模式是将您的子程序更改为函数,并让每个子程序返回一个true / false值,该值指示程序是否应该继续。另外,可以使用全局变量来存储错误,但是我更喜欢带有错误消息的out参数。
因此,如果我们使用我的模式,您的代码将变为:
Private Sub Button_Click()
Call DoSomething()
End Sub
Public Sub DoSomething()
Dim strErrDescription as String
If DoThing_1(strErrDescription) Then
If DoThing_2(strErrDescription) Then
//Could put a DoThing_3() 'here if desired
End If
End if
'Do something with strErrDescription now
End Sub
'Returns true if we should continue, false if an error happened and we should stop
Public Function DoThing_1(ByRef strErrorDescriptionOut) as Boolean
DoThing_1 = True 'Callers continue unless we encounter an error
Call DoThing_A() 'Note: If you want to follow the same pattern, you can add an if here as well
...
Call DoThing_B() 'Note: If you want to follow the same pattern, you can add an if here as well
...
strErrorDescriptionOut = "Error Here"
'End
DoThing_1 = false
Exit Function
...
Call DoThing_C()
...
End Function