{$I+} unit MyLog; {*******************************} interface {**********************************} var WriteTimeToLog :Boolean = False; WriteMillisecondsToLog :Boolean = False; LogElementsSeparator :String = ' '; Procedure WriteMyLog(const aStr :String); Procedure WriteMyLogEx(const aArgs :array of const; const aHeader :String = ''); // WriteMyLogEx(['vMin',vMin,'vMax',vMax], 'Testing') -> Testing vMin=20 vMax=40 {*****************************} implementation {*******************************} Uses System.SysUtils, System.Variants, System.IOUtils, System.SyncObjs, System.Diagnostics; var fInLog : TCriticalSection; fFS : TFormatSettings; fStopWatch : TStopwatch; fLogFile : TextFile; fLogOpened : Boolean; fFileBuf : array[1..4096] of Char; procedure AddStr(var aStr :String;const aAddStr :String);inline; begin aStr := aStr + aAddStr; end; Procedure WriteMyLog(const aStr :String); begin if not fLogOpened then Exit; var vFullStr :String; if WriteTimeToLog or WriteMillisecondsToLog then begin vFullStr := '['; if WriteTimeToLog then AddStr(vFullStr, DateTimeToStr(Now, fFS)); if WriteMillisecondsToLog then begin if WriteTimeToLog then AddStr(vFullStr, '-'); AddStr(vFullStr, IntToStr(fStopWatch.ElapsedMilliseconds)); end; AddStr(vFullStr, ']' + aStr); end else vFullStr := aStr; fInLog.Acquire; try try Writeln(fLogFile, vFullStr); Flush(fLogFile); except //Ignoring all exceptions end;{try} finally fInLog.Release; end; end; function PointerToStr(aPtr : Pointer):String; begin if aPtr=nil then Exit('nil') else Exit(IntToHex(UIntPtr(aPtr))); end; function ObjectToStr(aObj : TObject):String; begin if aObj=nil then Exit('[]nil') else Exit('['+aObj.ClassName+']'+PointerToStr(aObj)); end; Procedure WriteMyLogEx(const aArgs :array of const; const aHeader :String = ''); var vArgument :Boolean; vStr :String; procedure IncStr(const aAddStr :String); begin if vArgument then AddStr(vStr, aAddStr) else AddStr(vStr, '=' + aAddStr + LogElementsSeparator); end; begin if not fLogOpened then Exit; vArgument := True; vStr := aHeader; if vStr<>'' then AddStr(vStr, LogElementsSeparator); for var I := Low(aArgs) to High(aArgs) do begin with aArgs[I] do begin case VType of vtUnicodeString : IncStr(String(UnicodeString(VUnicodeString))); vtAnsiString : IncStr(String(AnsiString(VAnsiString))); vtWideString : IncStr(String(WideString(VWideString))); vtString : IncStr(String(VString^)); vtInteger : IncStr(IntToStr(VInteger)); vtInt64 : IncStr(IntToStr(VInt64^)); vtExtended : IncStr(FloatToStr(VExtended^, fFS)); vtBoolean : IncStr(BoolToStr(VBoolean, true)); vtCurrency : IncStr(CurrToStr(VCurrency^, fFS)); vtObject : IncStr(ObjectToStr(VObject)); vtClass : IncStr(VClass.ClassName); vtPointer : IncStr(PointerToStr(vPointer)); vtVariant : IncStr(VarToStr(VVariant^)); vtInterface : IncStr(PointerToStr(vInterface)); (* vtChar vtPChar vtWideChar vtPWideChar *) end;{case} end;{with} vArgument := not vArgument; end;{for i} WriteMyLog(vStr); end; procedure InitLogSubSystem; begin fLogOpened := True; try var vTmpPath := TPath.GetTempPath + PathDelim + 'MyLog'; CreateDir(vTmpPath); AddStr(vTmpPath, PathDelim + ExtractFileName(ParamStr(0))); var vLogFileName :String; var vInd := 0; repeat vLogFileName := vTmpPath + '.' + IntToStr(vInd) + '.log'; inc(vInd); until not FileExists(vLogFileName); AssignFile(fLogFile, vLogFileName); System.SetTextBuf(fLogFile, fFileBuf); ReWrite(fLogFile); fInLog := TCriticalSection.Create; except fLogOpened := False; end;{try} if fLogOpened then begin fFS := FormatSettings; fFS.DecimalSeparator := '.'; fFS.DateSeparator := '/'; fFS.ShortDateFormat := 'dd/mm/yy'; fFS.LongDateFormat := fFS.ShortDateFormat; fFS.TimeSeparator := ':'; fFS.ShortTimeFormat := 'hh:nn:ss'; fFS.LongTimeFormat := 'hh:nn:ss'; fStopWatch := TStopwatch.StartNew; end; end; procedure DoneLogSystem; begin try if fLogOpened then begin fLogOpened := False; CloseFile(fLogFile); fInLog.Free; end; except {Ignoring} end; end; initialization InitLogSubSystem; WriteMyLog('===================== Start of log ============================'); finalization WriteMyLog('===================== End of log =============================='); DoneLogSystem; end.