Установка 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. Так должно быть в любой другой версии.

Другие вопросы по тегам