zoukankan      html  css  js  c++  java
  • 在Delphi中的Log

    1、使用 Win32 API OutputDebugString

    procedure TForm1.BtnDebugClick(Sender: TObject);

    begin

       //这里调用OutputDebugString发送调试信息到调试器。在Delphi

       //里面,用View - Debug Windows - Event Log 来查看。

       OutputDebugString(PChar('测试OutputDebugString'));

    end;

    很简单。这个函数是Windows提供的,专门用来进行调试。调用后,将把字符串发送给当前的调试器,比如说IDE,调试器(Softice, ollydbg)等。对于Delphi来说,就是Delphi IDE本身。在程序运行的时候,可以通过View - Debug Windows - Event Log 来查看,如图:

    2、发送日志到操作系统日志记录。

    这个基本上使用在Release版本中,记录一些重要的信息,帮助用户反馈信息给开发人员。

    procedure TForm1.BtnEventClick(Sender: TObject);

    var

        h,b:THandle;

        msg:String;

        p:Pointer;

        i:integer;

        size:integer;

        q:^byte;

    begin

        //注册事件源,随便起了个名字。这个名字就是下图事件列表的’来源’一列

        //然后判断是否成功。

        //注意后面要注销

        h:=RegisterEventSource(nil, 'test1');

        if h = 0 then

        begin

            ShowMessage('注册事件源失败!');

            Exit;

        end;

        //这里记录一个字符串

        //这个字符串显示在下面第二个图选中的位置。

        msg:='记录字符串';

        ReportEvent(h,EVENTLOG_INFORMATION_TYPE,0, 0, nil, 1, 0, @msg, nil);

        //这里记录一块内存,size大小,里面随便填充一些int

        size:=32;

        //申请

        GetMem(p, size);

        q:=p;

        //填充这块内存

        for i:=0 to size - 1 do

        begin

            q^:=i;

            inc(q);

        end;

        //这里记录内存的内容。大小为size, 首字节的指针p

        //同样也有说明信息msg

        msg:='记录某块内存';

        ReportEvent(h,EVENTLOG_INFORMATION_TYPE , 0, 0, nil, 1, size, @msg, p);

        FreeMem(p);

        //注销事件源

        DeregisterEventSource(h);

    end;

    程序运行后,可以通过控制面板 – 管理工具 – 事件查看器来查看。上面的代码运行结果如图:.

    双击第一个事件,如图:

    双击第二个事件,如图:

    3、覆盖Assert

    Delphi内置了Assert调试过程,语法是

    Assert(cond, msg);

    如果cond为false,那么显示错误信息msg,并且触发异常(可在IDE里中断)。

    因为这个函数是编译器内置的,里面提供了源代码文件名、行号的信息,所以可以通过重写这个函数,完成日志记录的功能:

    1、加入初始化代码,保存旧的Assert函数地址,然后将新的赋入:

    initialization

       oldAssertErrorProc := AssertErrorProc;

       AssertErrorProc:=@OtherAssertProc;

    其中,新函数OtherAssertProc如下:

    procedure OtherAssertProc(const Message, Filename: string;

        LineNumber: Integer; ErrorAddr: Pointer);

    Var

       runErrMsg:String;

    begin

    runErrMsg := format('Error: %s, in file(%d): %s, Addr: %p',

                          [Message, LineNumber, FileName, ErrorAddr]);

    if IsConsole then

        Writeln(runErrMsg)

    else

        MessageBox(0, pChar(runErrMsg), 'Error Log by AssertLogs', 0);

    end;

    2、在程序中,就可以使用

       Assert(false, msg);来进行调用了。因为我们使用Assert来记录信息,所以条件一定是false保证函数被调用。运行结果如下图:

    这是通过MessageBox函数输出的,当然也可以通过其他方式显示或者记录。

    3、最后,将AssertErrorProc恢复初始值:

    finalization

    AssertErrorProc := oldAssertErrorProc;

    4、JCL库

    JCL库是著名的开源Delphi库,包括大量的函数、类,基本上分为系统、日期、调试、字符串等等。其中的JCLDebug库可以方便的列出代码的调用情况,也可以做到类似与Java的逐层打印调用栈。运行情况如下图:

    代码为:

    //这是一个日志函数,拼装日志信息

    function log(S:String):String;

    var

       f, proc:String;

       line:Integer;

       r:String;

    begin

       f:=FileByLevel(1); //获得调用它的文件名

       line:=LineByLevel(1); //获得调用它的行号

       proc:=ProcByLevel(1); //获得调用它的模块名

       Result:= f + ':' + IntToStr(line) + ' ' + proc + ' ' + S;

    end;

  • 相关阅读:
    岛田庄司《占星术杀人魔法》读后感
    OutputCache祥解
    ZOJ Monthly, June 2014 月赛BCDEFGH题题解
    接口和抽象类有什么差别
    C语言指针的初始化和赋值
    深入探讨this指针
    郁 繁体为“鬰” 古同 “鬱”
    socketpair的使用
    Android的FrameLayout使用要注意的问题
    下确界和上确界
  • 原文地址:https://www.cnblogs.com/larson/p/2568506.html
Copyright © 2011-2022 走看看