123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190 |
- unit Setup.LoggingFunc;
- {
- Inno Setup
- Copyright (C) 1997-2024 Jordan Russell
- Portions by Martijn Laan
- For conditions of distribution and use, see LICENSE.TXT.
- Logging functions
- }
- interface
- procedure Log(const S: String);
- procedure LogFmt(const S: String; const Args: array of const);
- procedure StartLogging(const Prefix: String);
- procedure StartLoggingWithFixedFilename(const Filename: String);
- function GetLogFileName: String;
- function GetLogActive: Boolean; { Returns True if logging was started or when debugging from the IDE }
- const
- SYesNo: array[Boolean] of String = ('No', 'Yes');
- implementation
- uses
- Windows, SysUtils, Shared.Int64Em, Shared.CommonFunc, Shared.FileClass, Setup.DebugClient;
- var
- LogFile: TTextFileWriter;
- LogFileName: String;
- LocalTimeBias: Integer64;
- procedure InitLocalTimeBias;
- var
- UTCTime, LocalTime: Integer64;
- begin
- GetSystemTimeAsFileTime(TFileTime(UTCTime));
- if FileTimeToLocalFileTime(TFileTime(UTCTime), TFileTime(LocalTime)) then begin
- Dec6464(LocalTime, UTCTime);
- LocalTimeBias := LocalTime;
- end;
- end;
- procedure GetFixedLocalTime(var ST: TSystemTime);
- { Like GetLocalTime, but uses our LocalTimeBias as the offset, which cannot
- change while the program is running }
- var
- FT: Integer64;
- begin
- GetSystemTimeAsFileTime(TFileTime(FT));
- Inc6464(FT, LocalTimeBias);
- FileTimeToSystemTime(TFileTime(FT), ST);
- end;
- procedure LogLogOpened;
- var
- Offset: Integer64;
- PlusOrMinus: Char;
- begin
- Offset := LocalTimeBias;
- if Longint(Offset.Hi) >= 0 then
- PlusOrMinus := '+'
- else begin
- PlusOrMinus := '-';
- { Negate it }
- Offset.Lo := not Offset.Lo;
- Offset.Hi := not Offset.Hi;
- Inc64(Offset, 1);
- end;
- Div64(Offset, 60 * 10000000);
- LogFmt('Log opened. (Time zone: UTC%s%.2u:%.2u)', [PlusOrMinus,
- Offset.Lo div 60, Offset.Lo mod 60]);
- end;
- procedure StartLogging(const Prefix: String);
- var
- Dir, DateStr, Filename: String;
- I: Cardinal;
- ST: TSystemTime;
- F: TTextFileWriter;
- begin
- if Assigned(LogFile) then
- Exit; { logging was already started }
- Dir := GetTempDir;
- GetFixedLocalTime(ST);
- DateStr := Format('%.4u-%.2u-%.2u', [ST.wYear, ST.wMonth, ST.wDay]);
- I := 1;
- while True do begin
- Filename := Dir + Format('%s Log %s #%.3u.txt', [Prefix, DateStr, I]);
- if not FileOrDirExists(Filename) then begin
- F := nil;
- try
- F := TTextFileWriter.Create(Filename, fdCreateNew, faWrite, fsRead);
- except
- on E: EFileError do begin
- { Don't propagate ERROR_FILE_EXISTS errors; just try again.
- (Yes, we already checked if the file existed first, but this helps
- to make it race-proof.) }
- if E.ErrorCode <> ERROR_FILE_EXISTS then
- raise;
- end;
- end;
- if Assigned(F) then begin
- LogFile := F;
- LogFileName := FileName;
- Break;
- end;
- end;
- Inc(I);
- end;
- LogLogOpened;
- end;
- procedure StartLoggingWithFixedFilename(const Filename: String);
- begin
- if Assigned(LogFile) then
- Exit; { logging was already started }
- LogFile := TTextFileWriter.Create(Filename, fdCreateAlways, faWrite, fsRead);
- LogFileName := FileName;
- LogLogOpened;
- end;
- function GetLogFileName: String;
- begin
- Result := LogFileName;
- end;
- function GetLogActive: Boolean;
- begin
- Result := Assigned(LogFile) or Debugging;
- end;
- procedure Log(const S: String);
- procedure WriteStr(const S: String);
- begin
- LogFile.Write(S);
- end;
- var
- ST: TSystemTime;
- LineStart, I: Integer;
- begin
- if Assigned(LogFile) then begin
- GetFixedLocalTime(ST);
- try
- WriteStr(Format('%.4u-%.2u-%.2u %.2u:%.2u:%.2u.%.3u ',
- [ST.wYear, ST.wMonth, ST.wDay, ST.wHour, ST.wMinute, ST.wSecond,
- ST.wMilliseconds]));
- LineStart := 1;
- { Lines except for last line }
- for I := 1 to Length(S) do begin
- if S[I] = #10 then begin
- WriteStr(Copy(S, LineStart, I - LineStart + 1));
- LineStart := I + 1;
- { Indent }
- WriteStr(' ');
- end;
- end;
- { Last line }
- if LineStart <= Length(S) then
- WriteStr(Copy(S, LineStart, Length(S) - LineStart + 1));
- WriteStr(#13#10);
- except
- { Failed to write? Close the file and don't log anything further. }
- try
- FreeAndNil(LogFile);
- except
- end;
- end;
- end;
- if Debugging then
- DebugNotifyLogMessage(S);
- end;
- procedure LogFmt(const S: String; const Args: array of const);
- begin
- if GetLogActive then
- Log(Format(S, Args));
- end;
- initialization
- InitLocalTimeBias;
- finalization
- if Assigned(LogFile) then begin
- Log('Log closed.');
- FreeAndNil(LogFile);
- end;
- end.
|