如何重构VB6代码以防止运行时错误

时间:2010-05-09 06:27:42

标签: error-handling vb6 runtime-error

VB6应用程序在各个地方遇到运行时错误。

我知道这是错误处理不当的结果,但是有可能分析代码以查看它对运行时错误的影响吗?

6 个答案:

答案 0 :(得分:3)

任何应用程序都容易受到运行时错误的影响,因为对外部资源的调用没有错误处理,因此您可以将这些点识别为开始。

我使用了一个免费工具(许多年前),可以将错误处理改编为VB6代码,这至少会记录错误及其发生的点。

这是:The HuntErr Addin for easy error handling in VB6

答案 1 :(得分:2)

您需要确保代码库中的每个方法(函数,子函数,属性......)都有一个错误处理语句。可能不是每一个都可能产生运行时错误,但这将保护应用程序在没有大量前期分析的情况下崩溃。

确保在任何带有标签的“On Error GoTo ...”的可执行代码行之前有一个语句,然后确保在该方法的底部放置带有一些错误处理代码的标签。我使用了一个名为MZ-Tools 3.0的免费工具,它允许您自动包含此文本。选项中有一个错误处理程序选项卡,用于指定要放入的文本和位置。这就是我的样子:

    On Error GoTo l{PROCEDURE_NAME}_Error

    {PROCEDURE_BODY}

    Exit {PROCEDURE_TYPE}

l{PROCEDURE_NAME}_Error:

    LogError "{MODULE_NAME}", "{PROCEDURE_NAME}", Err, Err.Description

然后我只确保LogError函数存在并将错误写入我可以查看的日志文件中。

答案 2 :(得分:1)

VB6应用程序中常见的运行时错误来源包括

  • 访问不存在的集合中的密钥
  • 在没有任何内容的对象上调用方法或属性
  • 当字符串为空时,使用CLng将字符串转换为数字
  • 访问超出其长度的数组(例如在调用Split之后,然后假设该字符串具有您期望的数量)

因此,除了执行其他人提出的建议并分析实际错误的来源之外,您还可以先在代码中查找这些区域,然后对它们进行适当的错误处理。请记住,通常最好的“错误处理”根本不涉及使用On Error,而是通过检查这些边界情况提前防止错误,例如

  • 如果Not Object is Nothing
  • 如果Len(字符串)> 0
  • 如果UBound(数组)> X

等...

答案 3 :(得分:0)

这里有一些很好的答案,On Error GoTo建议和bwarner提到的裂缝中的常见错误。

但是可能扩大范围并利用内置工具来分析代码,如断点,监视表达式,尤其适用于调试运行时错误,本地窗口(通常在调试时忽略,但功能非常强大)和调用堆栈。你可以从这里获得很多关于这方面的好消息:Debugging Your Code and Handling Errors

其他需要考虑的事情可能会有所帮助:

  1. 投资一个可以帮助您的工具 使用CodeSMART 2009 for VB6VB Project Analyzer等分析。
  2. 尝试移植现有应用程序 到VB.NET - 不是实际的端口和 使用,但要查看转换日志 对于需要修复的事情。

答案 4 :(得分:0)

根据Ryan的回答和回复中的评论,你不 将错误处理放在的每个例程中,只是每个事件和Sub Main()(和API回调,如果它们还没有它。)

  

API回调是指Win32API直接调用的例程,通常使用Declared传递给AddressOf函数。 (即,在代码中搜索AddressOf,并确保所有作为参数提到的例程都有错误处理程序,可以捕获错误并且不允许它们冒泡。)

我刚刚注意到这并没有真正回答原来提出的问题(虽然根据Ryan的回答给出了评论 是一个很好的第一步):一旦你有错误处理每个事件等,您将捕获所有错误,但您将无法直接分析所有错误发生的位置。您需要将错误记录扩展到至少记录错误的事件所调用的所有例程,以更准确地找到每个错误的确切来源。

答案 5 :(得分:0)

在VB6中,在没有错误处理的情况下调用Event函数时,会发生运行时错误。所以至少所有的事件处理函数(比如Form.Open())都应该被一个错误处理程序包围(是的,我知道VB6没有它们),这可以很好地实现(我们在所有应用程序中都这样做)像这样):

将此作为EVERY事件处理函数的第一行(它是一个大的有效标签,最后设置On Error):

¦¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯: On Error GoTo ErrorHandler:

现在在所有这些功能的末尾使用它:

¦____________________________________________________________________________________________________________________________________: Exit Sub
ErrorHandler: handleError CodeDb, "Form_frm_filter_deletecolum", "cmd_deletecolum_Click", err.Number, err.description, err.Source, err.LastDllError, err.Helpfile, err.HelpContext, Erl: err.Clear

但是用模块名称和函数名替换两个字符串。并用On Error Goto 0替换每个On Error Goto ErrorHandler

现在使用给定的参数创建一个函数handleError(在我的应用程序中它会自动向我们的错误跟踪系统发送错误报告),并显示一个很好的错误消息。

我们甚至推动了这一点,通过预先构建的过程向所有其他行添加类似的行(意味着非事件函数或其他函数调用的函数),以记住发生错误的行和累积完整的堆栈跟踪(是的,在VB6中堆栈跟踪!)。此外,此过程为每一行添加行号,因此它们在错误处理程序的Erl部分中给出。

我们的工具是作为一些MS Access模块​​编写的,所以我不能简单地为你提供它,但你知道你必须去哪里。