Установка Inno LoadStringFromFile завершается ошибкой, когда файл открыт в другом процессе
Чтобы проверить, запущена ли база данных (SQL Anywhere) и готова ли она к приему запросов, я выводю окно сообщения базы данных в файл журнала (текст), а затем пытаюсь прочитать его, используя LoadStringFromFile
, который я затем ищу конкретный текст, используя Pos
, Проблема в том, что это не удается (я полагаю), поскольку файл используется.
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;
Я также попытался скопировать файл журнала с помощью FileCopy
и попытаться прочитать из копии файла, но FileCopy
также не удается.
if not FileCopy(strTempPath + '\dbeng.log', strTempPath + '\dbengcopy.log', False) then
begin
Log('File copy failed.');
end;
Есть ли способ чтения из файла, который используется или другой способ сделать это?
2 ответа
Использовать TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone)
,
В версии Inno Setup для Unicode его использование затруднительно из-за плохого интерфейса класса.
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;
Код основан на коде TLama, размещенном в считанных байтах из файла в нужной позиции с помощью Inno Setup.
При порождении сервера базы данных используйте dbspawn
Утилита, которая предназначена для этой цели. Вы порождение dbspawn
вместе с командой dbeng/dbsrv, которую вы хотите запустить, и она запускает сервер для вас. Утилита dbspawn не возвращается до тех пор, пока сервер базы данных не будет запущен, запущен и готов к приему запросов, поэтому не нужно догадываться и не нужно читать файл журнала консоли.
Я не знаю, какую версию SQL Anywhere вы используете, но вот документация для v17. Так должно быть в любой другой версии.