【问题标题】:Is there a way to catch all exceptions (even those handled) with JCLDebug?有没有办法用 JCLDebug 捕获所有异常(甚至是处理的异常)?
【发布时间】:2011-06-20 17:45:32
【问题描述】:

我想使用 JCLDebug 记录所有引发的异常,包括已处理的异常。

有可能吗?

【问题讨论】:

    标签: delphi exception


    【解决方案1】:

    看看JclHookExcept单元中的JclAddExceptNotifier

    【讨论】:

    • @Melaum:这可能很有趣,但不幸的是我不会说德语。 (或者如果那不是德语,不管它是什么,我也不会说。)
    • @Smasher:好的。我也不会说荷兰语,而且我对日耳曼语的了解也不够多,无法一眼就能分辨出来。 :P
    • 没问题,我也不会说荷兰语,甚至英语也很好(我是巴西人),我所做的是使用谷歌翻译。 =)
    【解决方案2】:

    它不是基于 JCL,但它是完全开源的,适用于 Delphi 5 到 XE。

    这个logging mechanism 能够拦截任何异常。

    事实上,从 Delphi 6 开始,您可以在 RtlUnwindProc 中定义一个全局过程,以便在引发任何异常时启动:

    {$ifdef DELPHI5OROLDER}
    procedure RtlUnwind; external kernel32 name 'RtlUnwind';
    {$else}
    var
      oldUnWindProc: pointer;
    {$endif}
    
    procedure SynRtlUnwind(TargetFrame, TargetIp: pointer;
      ExceptionRecord: PExceptionRecord; ReturnValue: Pointer); stdcall;
    asm
      pushad
      cmp  byte ptr SynLogExceptionEnabled,0
      jz   @oldproc
      mov  eax,TargetFrame
      mov  edx,ExceptionRecord
      call LogExcept
    @oldproc:
      popad
      pop ebp // hidden push ebp at asm level
    {$ifdef DELPHI5OROLDER}
      jmp RtlUnwind
    {$else}
      jmp oldUnWindProc
    {$endif}
    end;
    
    
    oldUnWindProc := RTLUnwindProc;
    RTLUnwindProc := @SynRtlUnwind;
    

    此代码将启动以下功能:

    type
      PExceptionRecord = ^TExceptionRecord;
      TExceptionRecord = record
        ExceptionCode: DWord;
        ExceptionFlags: DWord;
        OuterException: PExceptionRecord;
        ExceptionAddress: PtrUInt;
        NumberParameters: Longint;
        case {IsOsException:} Boolean of
        True:  (ExceptionInformation : array [0..14] of PtrUInt);
        False: (ExceptAddr: PtrUInt; ExceptObject: Exception);
      end;
      GetExceptionClass = function(const P: TExceptionRecord): ExceptClass;
    
    const
      cDelphiExcept = $0EEDFAE0;
      cDelphiException = $0EEDFADE;
    
    procedure LogExcept(stack: PPtrUInt; const Exc: TExceptionRecord);
    begin
      LastError := GetLastError;
         (...) intercept the exception
      SetLastError(LastError); // code above could have changed this
    end;
    

    对于Delphi 5,我had to patch the VCL in-process,因为没有全局异常拦截器。

    【讨论】:

    • 最新版本支持 XE4/XE5 和 Win32/Win64 平台。
    • @Arnaud Bouchez:我究竟需要为 Delphi2006 下载什么?我想试试你的 SynLog 助手,在未处理的异常上写日志文件。您的链接没有准确说明需要哪些 .pas 文件。
    • 最简单的方法是下载mORMot nightly build archive,然后使用SynCommons.pas / SynLZ.pas / Synopse.inc / SynopseCommit.inc。要构建日志查看器,您需要整个 mORMot 框架,因为它使用它进行远程调试。或者你可以从synopse.info/files/LogView.zip下载LogView工具的编译版本
    • 使用此代码我能够拦截异常,但我如何获取堆栈的堆栈跟踪信息:PPtrUInt?
    • @MiguelFebres 你有几种方法——看看SynLog.pas是怎么做的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-16
    • 2010-09-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多