当函数中发生错误时,我想知道导致错误的事件顺序,尤其是当从十几个不同的地方调用该函数时。有什么方法可以在 VB6 中检索调用堆栈,还是我必须以艰难的方式进行(例如,每个函数和错误处理程序中的日志条目等)?
5 回答
您确实必须以艰难的方式来做,但这并不是那么难……说真的,一旦您编写了模板,就可以快速复制/粘贴/修改以匹配 Err.Raise 语句中的函数名称到实际的函数名称。
Private Function DoSomething(ByVal Arg as String)
On Error GoTo Handler
Dim ThisVar as String
Dim ThatVar as Long
' Code here to implement DoSomething...
Exit Function
Handler:
Err.Raise Err.Number, , "MiscFunctions.DoSomething: " & Err.Description
End Function
当您有嵌套调用时,这会在每个例程命中其处理程序并将其名称添加到错误描述时展开。在顶层函数中,您会获得一个“调用堆栈”,其中显示了被调用的例程列表,以及实际发生的错误的错误号和描述。这并不完美,因为您没有获得行号,但我发现您通常不需要它们来找到解决问题的方法。(如果你真的想要行号,你可以把它们放在函数中,并使用 Erl 变量在 Err.Raise 语句中引用它们。没有行号,它只返回 0。)
另外,请注意,在函数本身中,您可以使用消息中有趣变量的值引发您自己的错误,如下所示:
Err.Raise PCLOADLETTER_ERRNUM, , "PC Load Letter error on Printer """ & PrinterName & """"
(预览中的语法突出显示看起来很奇怪......我想知道它在发布时会是什么样子?)
我很确定你必须以艰难的方式做到这一点。在我以前的工作中,我们有一个非常优雅的带有 DCOM 组件的 VB6 错误处理过程。但是,每个方法都必须添加大量冗余代码,以至于我们有自己开发的工具可以为您插入所有代码。
我无法提供太多关于其实施的见解(因为我已经忘记了大部分内容,而且他们有可能将其视为商业机密)。值得注意的一件事是方法名称无法在运行时派生,因此它被添加为字符串变量(一些开发人员会复制粘贴而不是使用该工具,这会导致错误堆栈撒谎。 ..)。
高温高压
硬的手动方法几乎是唯一的方法。如果您查看此问题,有人建议使用名为 MZTools 的工具来为您完成大部分繁重的工作。
正如其他人所说(几年前,我明白了......但是还有很多人仍在使用 VB6!:)),我认为不可能以编程方式检索调用堆栈,除非您使用一些第 3 方工具。
但是,如果您出于调试目的需要这样做,您可以考虑在被调用例程中添加一个可选输入字符串变量,如果您将输入调用者的名称。
Sub MyRoutine
(...) ' Your code here
call DoSomething (Var1, Var2, Var3, "MyRoutine")
' ^
' Present routine's name -----------+
(...) ' Your code here
End Sub
Public DoSomething (DoVar1, DoVar2, DoVar3, Optional Caller as string = "[unknown]")
Debug.Print " DoSomething Routine Called. Caller = " & Caller
... ' (your code here)
End Sub
也许不是那么优雅,但它对我有用。
问候, Max - 意大利
Compuware(或者当时是 Numega)DevStudio for Visual Basic 6 曾经这样做过。方法是在每个调用中添加添加工具,该调用调用添加到代码堆栈的非常小的片段。在出现任何错误时,它会转储该调用堆栈,然后执行诸如邮件或将所有调试信息发布到网络服务器之类的操作。添加和删除检测是一个潜在的致命操作(尤其是在当时,当我们使用 VSS 作为我们的源代码控制时),但如果它有效,它就会运作良好。
正如Darrel 指出的那样,您可以通过使用 MZTools 并设置模板来添加一些非常相似的东西。这需要大量的工作,并且可能比奖励更努力,但如果你很难找到错误,它可能会有所帮助)。