【问题标题】:Is it possible to retrieve the call stack programmatically in VB6?是否可以在 VB6 中以编程方式检索调用堆栈?
【发布时间】:2010-09-12 18:16:37
【问题描述】:

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

【问题讨论】:

    标签: vb6 runtime callstack


    【解决方案1】:

    正如其他人所说(几年前,我明白了......但是还有很多人仍在使用 VB6!:)),我认为不可能以编程方式检索调用堆栈,除非您使用一些 3rd-party 工具。

    但如果您出于调试目的需要这样做,您可以考虑在被调用例程中添加一个可选输入字符串变量,如果您将输入调用者的姓名。

    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
    

    也许不是那么优雅,但它对我有用。

    问候, 马克斯 - 意大利

    【讨论】:

    • 谁说过 VB6 很优雅?
    【解决方案2】:

    您确实必须以艰难的方式来做,但并不是所有都很难......说真的,一旦你编写了一次模板,它就是一个快速复制/粘贴/修改以将 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 & """"
    

    (预览中的语法突出显示看起来很奇怪......我想知道它在发布时会是什么样子?)

    【讨论】:

      【解决方案3】:

      Compuware(或者当时是 Numega)DevStudio for Visual Basic 6 曾经这样做过。方法是在每个调用中添加添加工具,该调用调用添加到代码堆栈的非常小的 sn-p。在出现任何错误时,它会转储该调用堆栈,然后执行诸如邮件或将所有调试信息发布到网络服务器之类的操作。添加和删​​除检测是一项潜在的致命操作(尤其是在当时,当我们使用 VSS 作为我们的源代码控制时),但如果它有效,它就会运作良好。

      作为Darrel pointed out,您可以通过使用 MZTools 并设置模板来添加一些非常相似的内容。这需要大量的工作,并且可能比奖励更努力,但如果你很难找到错误,它可能会有所帮助)。

      【讨论】:

        【解决方案4】:

        硬的手动方法几乎是唯一的方法。如果您查看this 问题,有人建议使用一个名为 MZTools 的工具来为您完成大部分繁重的工作。

        【讨论】:

        • 我多年来一直在使用 MZTools,我同意它是一个很棒的工具。但是,我一直在寻找“穷人的堆栈跟踪”的替代方法。我不认为有,但我认为在这里问不会有什么坏处。
        • 我建议远离 MZTools。这不是过去的样子(例如,它不是免费的,而且没有足够的用处,不值得付费,恕我直言)这也不是“唯一”的方式。还有其他方法可以获取调用堆栈,如果您要使用 Windows API 等从内存中提取数据,等等等等等等……更难的方法。
        【解决方案5】:

        我很确定你必须努力做到这一点。在我之前的工作中,我们有一个非常优雅的带有 DCOM 组件的 VB6 错误处理过程。但是,每个方法都必须添加大量冗余代码,以至于我们有自己开发的工具可以为您插入所有代码。

        我无法提供太多关于其实施的见解(因为我已经忘记了大部分内容,而且他们有可能将其视为商业机密)。值得注意的一件事是方法名称无法在运行时派生,因此它被添加为字符串变量(一些开发人员会复制粘贴而不是使用该工具,这会导致错误堆栈撒谎。 ..)。

        HTH

        【讨论】:

        • 这是我知道的唯一方法。如下所示,MZTools 可以提供帮助。在您的错误处理程序模板中,如果您要传播错误,请将您当前的函数/子附加到 err.source。
        • 我确信没有办法按照我的要求去做,所以我会接受这个答案。
        猜你喜欢
        • 2010-12-13
        • 1970-01-01
        • 2010-09-06
        • 2020-07-16
        • 2021-07-13
        • 1970-01-01
        • 2020-05-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多