是否可以在VB6中以编程方式检索调用堆栈?

时间:2020-03-06 14:40:04  来源:igfitidea点击:

当一个函数中发生错误时,我想知道导致该错误的事件的顺序,尤其是当从十几个不同的地方调用该函数时。有什么方法可以检索VB6中的调用堆栈,还是我必须用困难的方式(例如,每个函数和错误处理程序中的日志条目等)进行操作?

解决方案

我敢肯定,我们必须用艰辛的方式做到这一点。在我的上一个工作中,我们对带有DCOM组件的VB6有一个非常优雅的错误处理过程。但是,必须在每个方法中添加很多冗余代码,以至于我们拥有了自己开发的工具才能为我们插入所有代码。

我不能对它的实现提供太多的见解(两者都是因为我已经忘记了大部分,而且有可能他们会认为它是商业秘密)。突出的一件事是方法名称无法在运行时派生,因此将其作为字符串变量添加(某些开发人员会复制粘贴而不是使用工具,这会导致错误堆栈被掩盖。 ..)。

高温超导

困难的手动方法几乎是唯一的方法。如果我们检查出此问题,则有人建议使用一个名为MZTools的工具,它将为我们完成很多繁重的工作。

使用Compuware(或者当时是Numega)用于Visual Basic 6的DevStudio可以做到这一点。方式是在每个调用中添加一个指令,这些调用调用了一个添加到代码堆栈中的非常小的代码段。遇到任何错误时,它将转储该调用堆栈,然后执行邮件或者将所有调试信息发布到Web服务器之类的操作。添加和删​​除该工具是一种潜在的致命操作(尤其是在那时,当我们使用VSS作为源代码控制时),但是如果它起作用,它将很好地工作。

正如Darrel所指出的,我们可以使用MZTools并设置模板来添加非常类似的内容。它的工作量很大,而且可能比获得的回报还多,但是如果我们很难找到错误,可能会有所帮助)。

我们确实必须用困难的方式来做,但是实际上并没有那么难...认真地说,一旦编写了模板一次,它就可以快速复制/粘贴/修改以匹配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

嵌套调用后,当每个例程到达其Handler并将其名称添加到错误描述中时,此过程便会消失。在顶层函数中,我们将获得一个"调用堆栈",其中显示了所调用例程的列表以及错误号和实际发生的错误的描述。这并不完美,因为我们没有行号,但是我发现我们通常不需要它们来找到解决问题的方法。 (如果我们确实需要行号,则可以将它们放入函数中,并使用Erl变量在Err.Raise语句中进行引用。如果没有行号,则仅返回0。)

另外,请注意,在函数本身中,我们可以使用消息中有趣变量的值引发自己的错误,如下所示:

Err.Raise PCLOADLETTER_ERRNUM, , "PC Load Letter error on Printer """ & PrinterName & """"

(语法突出显示在预览中看起来很奇怪……我想知道发布后的外观如何?)