在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;

原文地址:https://www.cnblogs.com/larson/p/2568506.html