【问题标题】:Is it possible to have a global exception hook?是否可以有一个全局异常钩子?
【发布时间】:2011-02-07 09:30:38
【问题描述】:

我的代码很好地涵盖了异常处理(try..except)。一些异常预计不会发生,一些异常经常发生,这是可以预料的。现在我想为这段代码添加一些自动化测试。最好知道在执行过程中发生了多少异常,这样我以后可以查看是否引发了预期的数量或发生了任何意外情况。我不想用调试代码把每个异常处理块都弄得一团糟,所以我的问题是:

有没有办法在所有其他异常处理块之前安装某种全局异常处理程序?我正在寻找一个记录这些异常的中心位置。

感谢您的任何建议!

(如果这很重要:它是 Delphi 2009)

【问题讨论】:

    标签: delphi exception-handling


    【解决方案1】:

    您可以执行以下操作:

    • 保留 System.RaiseExceptObjProc 变量的值,该变量在普通 Delphi 应用程序中指向 SysUtils.RaiseExceptObject
    • 创建您自己的“RaiseExceptObject”过程并将其分配给 RaiseExceptObjProc 变量
    • 在您自己的“RaiseExceptObject”过程中,您可以做任何您想做的事情,然后调用保存的 RaiseExceptObjProc 值

    详情参见上面的变量和过程声明。

    【讨论】:

    • 哇哦!就是这样:) 非常感谢这个提示!并记录在案:1)RaiseExceptObjProc 的签名:procedure(P: PExceptionRecord) 2)看来我不必在我的处理程序中调用旧的RaiseExceptObjProc 3)我在某处读到自 Delphi 2009 以来可用的地方(对我有好处),但我不确定
    • 好的 SysUtils.pas 已经分配了RaiseExceptObjProc。也许这确实应该由我的处理程序调用。
    • 嘿,你能举个例子吗? :)
    • 对于使用此函数指针的代码示例,请查看stackoverflow.com/a/6415902/458259 - 适用于 Win32 和 Win64 平台上的 Delphi 5 到 XE4。
    • 虽然这很好用,但我发现它的一个问题是它会在之前捕获所有异常,无论它们如何处理或是否处理。这可能会导致异常问题,这些异常会被您的代码故意吃掉/吞下,因为预计会失败。我使用这种挂钩方法来捕获和记录服务应用程序中的所有异常,但尚未找到抑制此类异常的方法。
    【解决方案2】:

    我认为你可以使用AddVectoredExceptionHandler API 函数。

    这里有一个使用方法的小例子:

    var
      f : TFileStream;
    
        function VectoredHandler(ExceptionInfo : PEXCEPTION_POINTERS): LongInt; stdcall;
        var 
          s : String;
        begin
          S := Format('Exception code %x address %p'#10#13, [ExceptionInfo^.ExceptionRecord^.ExceptionCode,
           ExceptionInfo^.ExceptionRecord^.ExceptionAddress]);
           f.WriteBuffer(PChar(s)^, Length(s) * sizeof(wchar));
           FlushFileBuffers(f.Handle);
          OutputDebugString(PChar(Format('ExceptionCode: %x', [ExceptionInfo^.ExceptionRecord^.ExceptionCode])));
          result := EXCEPTION_CONTINUE_SEARCH ;
        end;
    
    
        initialization
          AddVectoredExceptionHandler(0, VectoredHandler);
    

    【讨论】:

    • 这会在 win32 级别捕获异常,这是 Dmitry Arefiev 的解决方案,但我更符合您的预期。
    • 感谢您指出这个函数,我认为这对于做纯 Win32 的人来说会很方便。就我而言,德米特里的解决方案更简单。
    • +1 因为我只需要这个 API 调用来支持旧版本的 Delphi(例如 Delphi 6-7),其中 RaiseExceptObjProc 不存在。
    【解决方案3】:

    您可以向madExcept 添加一个自定义处理程序,这将允许您获得完整的堆栈跟踪,但也可以继续。

    【讨论】:

    • @Arafangion 我会先阅读 madExcept 的文档,它会告诉你你需要知道的一切。本质上,您创建了一个异常处理程序(try/except),然后将异常对象传递给 HandleException 以供 madExcept 处理,它会发挥作用。
    • 文档对如何处理 未捕获 异常并不清楚,特别是当您开始关心 SEH 异常处理时。
    【解决方案4】:

    JCL 有它自己的异常对话框。只需将此对话框添加到您的项目中,它将处理所有意外异常。位于此 JCL 文件夹中的详细信息:jcl\experts\debug。还有一个howto文本文件,它一步一步地描述了如何使用它。

    【讨论】:

    • OP 也在寻找挂钩到 handled 异常。
    猜你喜欢
    • 2012-11-02
    • 2019-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-18
    • 1970-01-01
    • 2011-03-29
    • 1970-01-01
    相关资源
    最近更新 更多