我已将Application.OnException设置为自定义异常处理程序,以便我可以记录崩溃并提供退出选项。但是,我现在发现这甚至在我已经处理的异常上运行,例如,在验证数字输入时出现的异常。有没有办法让自定义异常处理程序仅在未处理的异常上运行?
编辑:事实证明,当我在调试器外部运行时,我得到了预期的行为。也许这只是一个调试器的事情。至少可以说,我没有发现Delphi调试器与异常的交互是直观的。
答案 0 :(得分:14)
如果调试器内外的行为发生变化,那么它实际上并不是你的程序会告诉你异常。我在我的网站上写过这个现象:
Why do I continue getting error messages even after I have written an exception handler?
摘录:
在默认设置中,只要程序中发生异常,Delphi IDE就会通知您....重要的是要意识到,在那时,程序的异常处理代码的 none 已经运行了。这都是德尔福本身;它作为调试器的特殊状态允许它获得程序中任何异常的第一个通知,甚至在程序知道它之前。
在您关闭Delphi的消息框后,执行将暂停在源代码的最佳行中,Delphi可以找到代表异常的来源。按“运行”按钮可恢复程序。控制将最终传递到下一个或除外 块。在恢复程序之前,您可以使用各种调试工具。您可以检查范围内任何变量的值,甚至可以修改它们的值。
那么,您如何通知Delphi您已经处理了异常?你没有 - 因为你的程序还没有处理它。为什么调试器无法检测您的程序是否 来处理异常?因为为了做到这一点,它需要进一步执行你的程序。检测缺少异常处理程序就像解决暂停问题一样。确定是否要处理异常的唯一方法是让程序运行,然后查看异常是否得到处理。但到那时,进行任何调试都为时已晚,因此调试器别无选择,只能在第一次检测到异常时暂停程序,然后让你弄清楚该怎么做。
我的文章接着描述了一些避免调试器捕获某些异常的方法,总结如下:
我的文章中还没有包含其他选项:
你说你正在验证数字输入。这对我来说听起来像是在调用StrToInt
,然后在输入不是有效整数时捕获EConvertError
异常。这是一种验证输入的昂贵方法。而不是使用TryStrToInt
,它将告诉您转换是否成功,或StrToIntDef
,它将静默返回默认值而不是引发异常。另一个选项是普通旧Val
,它尝试转换字符串,如果失败,它会告诉您字符串中的哪个位置导致失败。如果您希望为转换使用尽可能多的字符,然后在下一个非数字字符处继续解析,则Val
特别有用。
答案 1 :(得分:4)
引用TApplication.OnException
上的文档(Delphi 7)"Use OnException to change the default behavior that occurs when an exception is not
handled by application code."
因此:OnException事件处理程序中只能使用未处理的异常。您遇到的可能是Delphi IDE打破异常。这是(至少在Delphi 7中)可配置的。
在Delphi 7中,您可以通过单击Tools-> Debugger Options菜单进行配置。然后选择“语言异常”并取消选中“停止Delphi异常”复选框。但是在其他delphi版本中可能会有所不同。
答案 2 :(得分:1)
另一种方法可能是不使用Application.OnException。但要简单地捕获“主要”功能中的所有异常。这样,您可以捕获之前未缓存的所有异常,记录异常,然后崩溃。
答案 3 :(得分:1)
Application.OnException只应触发未处理的异常。在try-except块中重新引发异常将导致异常由Application.OnException处理。对于引发异常的输入验证,您可以向用户显示消息,然后仅在您希望将其记录到错误日志中时才重新引发异常。