Inno-Setup-issrc/Projects/Src/Setup.LoggingFunc.pas

191 lines
4.8 KiB
ObjectPascal

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.