Delphi 调试日子 - TLogger

本文介绍了一种在Delphi中使用的简单而有效的调试工具——Logger。通过示例代码展示了如何利用预编译指令来灵活地控制调试信息的输出,进而帮助开发者高效地定位问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

这段时间又开始用delphi了,才发现我对它这么的不熟悉!

简单的而有效的调试工具 Logger 这个是“榕树下”的作品,小巧而精悍。稍微调整了一下。在需要的地方加入

{$IFDEF DEBUG}
        Logger.WriteLog('SetKeyDatetime ok %s', [DateTimeToStr(FKeyDatetime)], llDebug);
     {$ENDIF}

当然如果在 每个文件中加入一个 {$I debug.inc},通过这个文件可以方便的控制调试输出,比如

debug.inc文件内容:
     {$IFDEF DEBUG}
        {$DEFINE MENUBUIDE}//菜单构建
        //{$DEFINE MENULOAD}//菜单载入
        //{$DEFINE MENURELATION}//菜单关联

        {$DEFINE MENUACTION}//菜单动作
        {$DEFINE DEBUGREPORT}//报表调试
        {$DEFINE DEBUGMAINTAIN}//维护功能调试
    {$ENDIF }

如果使用了以上debug.inc这时logger不会输出,编译跳过。
     {$IFDEF MENULOADDEBUG}
          Logger.WriteLog('Menuload ok %s',llDebug);
     {$ENDIF}

转载于:https://www.cnblogs.com/hieroly/p/3459610.html

Delphi Logger { 超简单实用的DELPHI日志单元 1.0.0 优化版 引用本单元即可使用 一共四个方法 procedure log4error(msg: AnsiString); //写ERROR级别的日志 procedure log4info(msg: AnsiString); //写INFO级别的日志 procedure log4debug(msg: AnsiString); //写DEBUG级别的日志 function log4filename():AnsiString; //得到当前日志文件全名 一个配置文件 log4me.ini #配置文件和主程序在同一目录.没有这个文件或不在主目录中则不写日志 [log4me] #path,日志的存放目录.必须是主程序目录及子目录. #例子:主程序目录 #path=. #例子:子目录 #path=temp\logs path=logs #level,日志等级,只能是 error,info,debug之一 #为error时,只有log4error打印的日志被输出. #为info时,log4error和log4info打印的日志被输出. #为debug时,log4error,log4info,log4debug打印的日志都被输出. level=info 一个可选工具 tail.exe 命令行中输入 >tail.exe -1000f 日志文件名 即可动态查看日志输出 或用程序调用 var cmd :AnsiString; log_file:AnsiString; begin log_file := log4filename(); //得到当前日志文件全名 cmd := ExtractFilePath(ParamStr(0)) + 'tail.exe -1000f "'+ log_file +'"'; WinExec(PAnsiChar(cmd),SW_SHOWNORMAL); //程序调用 tail.exe工具来查看日志 } unit log4me; interface uses classes, sysutils, ComObj, windows,IniFiles; procedure log4error(msg: AnsiString); //写ERROR级别的日志 procedure log4info(msg: AnsiString); //写INFO级别的日志 procedure log4debug(msg: AnsiString); //写DEBUG级别的日志 function log4filename():AnsiString; //得到当前日志文件全名 var log_filename: AnsiString; //日志文件全名 implementation var log_ThreadLock: TRTLCriticalSection; // 临界区 log_fileStream: TFileStream; log_filepath: AnsiString; //日志文件路径 log_initime:TDateTime; log_doerror, log_dodebug, log_doinfo: Boolean; procedure log_init(); var tmpStr:String; begin log_doerror := False; log_dodebug := False; log_doinfo := False; if FileExists(ExtractFilePath(ParamStr(0)) + 'log4me.ini') then begin with TIniFile.Create(ExtractFilePath(ParamStr(0)) + 'log4me.ini') do try log_filepath := ExtractFilePath(ParamStr(0)) + '\' + ReadString('log4me','path','logs') + '\'; tmpStr := LowerCase(ReadString('log4me','level','info')); log_doerror := (tmpStr = 'debug') or (tmpStr = 'info') or (tmpStr = 'error'); log_doinfo := (tmpStr = 'debug') or (tmpStr = 'info'); log_dodebug := (tmpStr = 'debug') ; finally Free; end; end; log_initime := Now; end; procedure log4me_addLog(filename: AnsiString; p: PAnsiChar); var fmode :Word; tmp:AnsiString; begin //进入临界区,多线程时可以保护资源 EnterCriticalSection(log_ThreadLock); try try //如果要写的日志文件和打开的不同(在程序第一次运行和跨天的时候出现) //则关闭打开的日志文件。 if filename log_filename then begin log_filename := filename; if Assigned(log_fileStream) then begin log_fileStream.Free; log_fileStream := nil; end; end; //如果要写的日志文件没有打开(在程序第一次运行和跨天的时候出现) //则打开日志文件。 if not Assigned(log_fileStream) then begin if FileExists(log_filename) then fmode := fmOpenWrite or fmShareDenyNone else fmode := fmCreate or fmShareDenyNone ; log_fileStream := TFileStream.Create(log_filename,fmode); log_fileStream.Position := log_fileStream.Size; end; //在日志文件中写入日志 log_fileStream.Write(p^, strlen(p)); except on E:Exception do begin try tmp := ExtractFilePath(ParamStr(0)) + 'log4me_err.log'; if FileExists(tmp) then fmode := fmOpenWrite or fmShareDenyNone else fmode := fmCreate or fmShareDenyNone ; with TFileStream.Create(tmp, fmode) do begin Position := Size; tmp := FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz', Now) + ' ' + E.Message + #13#10; Write(tmp[1],Length(tmp)); Free; end; except end; end; end; finally //无论如何,离开临界区 LeaveCriticalSection(log_ThreadLock); end; end; procedure log4write(msg: AnsiString); var strline: AnsiString; begin // 最多每秒重加载一次配置文件 if (Now() - log_initime) > (1/(24*60*60)) then log_init(); //日志开头加时间 strline := FormatDateTime('hh:nn:ss.zzz', Now) + ' ' + msg + #13#10; //写到当天的日志文件中 log4me_addLog(log_filepath + FormatDateTime('yyyy-mm-dd', Now) + '.log', PAnsiChar(strline)); end; //-----下面4个是对外方法------------------------- function log4filename():AnsiString; begin Result := log_filename; end; procedure log4error(msg: AnsiString); begin if log_doerror then log4write('[error]' + msg); end; procedure log4info(msg: AnsiString); begin if log_doinfo then log4write('[info ]' + msg); end; procedure log4debug(msg: AnsiString); begin if log_dodebug then log4write('[debug]' + msg); end; // ----------- 类初始化 -------------// initialization InitializeCriticalSection(log_ThreadLock); log_init; log4info('log4me:application starting....'); // ----------- 类销毁 -------------// finalization log4info('log4me:application stoping....'); DeleteCriticalSection(log_ThreadLock); if Assigned(log_fileStream) then log_fileStream.Free; end.
(******************************************************************************)<br>(* 模 块 名: HSLogger4D.Pas *)<br>(* 别 名: 多任务线程安全日志接口-进程独立版 *)<br>(* 作 者: Unsigned(僵哥) *)<br>(* 说 明: 基于线程安全和文件缓存的单例多线程同步日志记录接口,本接口由一个 *)<br>(* Delphi版本的动态链接库来提供相应的功能,采用Delphi的 String 类型 *)<br>(* 传递参数,使用时请注意调用方式与Delphi一致,不建议使用于 Delphi *)<br>(* 以外的语言环境,由此所引发的后果,作者不承担任何责任 *)<br>(* 附带文件: HSLogger4D.DLL *)<br>(* 版 本 号: 1.1 *)<br>(* 创 建 于: 2007-07 *)<br>(* 备 注: 本接口属进程独立版不处理多进程间同步 *)<br>(* *)<br>(* 修改记录: 2007-07-13 创建最初版本 *)<br>(* 2007-07-14 修正多线程内存管理冲突 *)<br>(******************************************************************************)<br><br>unit HSLogger4D;<br><br>interface<br>uses<br> Windows;<br>(*********************************)<br>(* 功 能:记录日志 *)<br>(* 参数1:日志文件名,支持相对路径 *)<br>(* 参数2:日志内容,自行控制换行符 *)<br>(* 参数3:记录日志后是否关闭文件 *)<br>(* (不会释放其它资源) *)<br>(* 返回值:0=成功,非0=LastError *)<br>(*********************************)<br>function WriteLogThreadsafe(<br> FileName : String;<br> LogString : String;<br> CloseFileAfterWrote : BOOL<br> ) : DWORD;overload;<br><br>function WriteLogThreadsafe(<br> FileName : String;<br> LogString : String<br> ) : DWORD;overload;<br>(*********************************)<br>(* 功 能:关闭日志文件 *)<br>(* 参数1:日志文件名,支持相对路径 *)<br>(* 参数2:记录日志文件关闭后是否 *)<br>(* 释放其它相关资源 *)<br>(*********************************)<br>procedure CloseFile(<br> FileName : String;<br> FreeAfterClose : BOOL = true<br> );<br><br>(*********************************)<br>(* 功 能:关闭所有日志文件 *)<br>(* 参数1:记录日志文件关闭后是否 *)<br>(* 释放其它相关资源 *)<br>(*********************************)<br>procedure CloseAllFile(<br> FreeAfterClose : BOOL = false<br> );<br><br>(*********************************)<br>(* 功 能:强制缓存写入文件 *)<br>(* 参数1:日志文件名,支持相对路径 *)<br>(* 参数2:写入文件后是否关闭文件 *)<br>(* (不会释放其它资源) *)<br>(* 返回值:0=失败,非0=成功 *)<br>(*********************************)<br>function FlushFileToDisk(<br> FileName : String;<br> CloseFileAfterFlush : BOOL = true<br> ) : BOOL;<br><br>(*********************************)<br>(* 功 能:强制缓存写入文件 *)<br>(* 参数1:写入文件后是否关闭文件 *)<br>(* (不会释放其它资源) *)<br>(*********************************)<br>procedure FlushAllFileToDisk(<br> CloseFileAfterFlush : BOOL = false<br> );<br><br>var<br> CloseFileAfterWrote:BOOL=false;<br><br>implementation<br><br>(******************************************************************************)<br>(* *)<br>(* <<日志接口定义>> *)<br>(* 注:请保持与源接口一致 *)<br>(******************************************************************************)<br>type<br> (*Logger Interface*)<br> ILogger=interface<br> ['{E43E419D-26AD-48e6-8097-19622CC2043E}']<br> function WriteLog(<br> FileName : String;<br> LogString : String;<br> CloseFileAfterWrote : BOOL = true<br> ) : DWORD;<br><br> procedure CloseFile(<br> FileName : String;<br> FreeAfterClose : BOOL = true<br> );<br><br> procedure CloseAllFile(<br> FreeAfterClose : BOOL = true<br> );<br><br> function FlushFileToDisk(<br> FileName : String;<br> CloseFileAfterFlush : BOOL = true<br> ) : BOOL;<br><br> procedure FlushAllFileToDisk(<br> CloseFileAfterFlush : BOOL = true<br> );<br> end;<br><br> (*Logger Import statement*)<br> function HSLoggerObject: ILogger; stdcall;<br> external 'HSLogger4D.dll'<br> name 'HSLoggerObject';<br><br>(*Write Log-String to file*)<br>(*********************************)<br>(* 功 能:记录日志 *)<br>(* 参数1:日志文件名,支持相对路径 *)<br>(* 参数2:日志内容,自行控制换行符 *)<br>(* 参数3:记录日志后是否关闭文件 *)<br>(* (不会释放其它资源) *)<br>(*********************************)<br>function WriteLogThreadsafe(<br> FileName : String;<br> LogString : String;<br> CloseFileAfterWrote : BOOL<br> ) : DWORD;<br>begin<br> Result:=HSLoggerObject.WriteLog(<br> FileName,<br> LogString,<br> CloseFileAfterWrote<br> );<br>end;<br><br>function WriteLogThreadsafe(<br> FileName : String;<br> LogString : String<br> ) : DWORD;<br>begin<br> Result:=WriteLogThreadsafe(<br> FileName,<br> LogString,<br> CloseFileAfterWrote<br> );<br>end;<br><br>(*Close one Logfile,and free logfile-Object if FreeAfterClose was set to TRUE*)<br>(*********************************)<br>(* 功 能:关闭日志文件 *)<br>(* 参数1:日志文件名,支持相对路径 *)<br>(* 参数2:记录日志文件关闭后是否 *)<br>(*********************************)<br>procedure CloseFile(<br> FileName : String;<br> FreeAfterClose : BOOL);<br>begin<br> HSLoggerObject.CloseFile(<br> FileName,<br> FreeAfterClose<br> );<br>end;<br><br>(*Close All Logfile,and free logfile-Object if FreeAfterClose was set to TRUE*)<br>(*********************************)<br>(* 功 能:关闭所有日志文件 *)<br>(* 参数1:记录日志文件关闭后是否 *)<br>(*********************************)<br>procedure CloseAllFile( FreeAfterClose : BOOL = false );<br>begin<br> HSLoggerObject.CloseAllFile(FreeAfterClose);<br>end;<br><br>(*********************************)<br>(* 功 能:强制缓存写入文件 *)<br>(* 参数1:日志文件名,支持相对路径 *)<br>(* 参数2:写入文件后是否关闭文件 *)<br><br>(* 返回值:0=失败,非0=成功 *)<br>(*********************************)<br>function FlushFileToDisk( FileName : String;<br> CloseFileAfterFlush : BOOL<br> ) : BOOL;<br>begin<br> Result:=HSLoggerObject.FlushFileToDisk(<br> FileName,<br> CloseFileAfterFlush<br> );<br>end;<br><br>(*********************************)<br>(* 功 能:强制缓存写入文件 *)<br>(* 参数1:写入文件后是否关闭文件 *)<br>(*********************************)<br>procedure FlushAllFileToDisk( CloseFileAfterFlush : BOOL );<br>begin<br> HSLoggerObject.FlushAllFileToDisk(CloseFileAfterFlush);<br>end;<br>end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值