To check to see when a database (SQL Anywhere) is fired up and ready to receive requests I am outputting the database message window to a log (text) file and then attempting to read this using LoadStringFromFile
, which I then search for specific text using Pos
. The problem is that this fails (I assume) as the file is in use.
Exec(strInstallPath + '\Bin32\dbeng17.exe', '-n ' + strEngineName + ' "' + strInstallPath + '\Database\Olympus.db" -n ' + strDatabaseName + ' -gdall -xtcpip -ti0 -c25p -ot "' + strTempPath + '\dbeng.log"', '', SW_HIDE,
ewNoWait, intResultCode);
if not LoadStringFromFile(strTempPath + '\dbeng.log', astrDatabaseEngineLog) then
begin
Log('Loading string from file failed.');
end;
I have also tried to copy the log file using FileCopy
and attempt to read from the copy of the file, but FileCopy
also fails.
if not FileCopy(strTempPath + '\dbeng.log', strTempPath + '\dbengcopy.log', False) then
begin
Log('File copy failed.');
end;
Is there any way to read from a file that is in use or another way to do this?
Use the TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone)
.
In Unicode version of Inno Setup (the only version as of Inno Setup 6), its use is tricky due to a bad interface of the class.
function BufferToAnsi(const Buffer: string): AnsiString;
var
W: Word;
I: Integer;
begin
SetLength(Result, Length(Buffer) * 2);
for I := 1 to Length(Buffer) do
begin
W := Ord(Buffer[I]);
Result[(I * 2)] := Chr(W shr 8); // high byte
Result[(I * 2) - 1] := Chr(Byte(W)); // low byte
end;
end;
function LoadStringFromLockedFile(
const FileName: string; var S: AnsiString): Boolean;
var
Buffer: string;
Stream: TFileStream;
begin
Result := True;
try
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone);
try
SetLength(Buffer, Stream.Size div 2);
Stream.ReadBuffer(Buffer, Stream.Size);
S := BufferToAnsi(Buffer);
finally
Stream.Free;
end;
except
Result := False;
end;
end;
The code is based on TLama's code posted in Read bytes from file at desired position with Inno Setup.