在另一个进程中打开文件时,Inno Setup LoadStringFromFile 失败

Inno Setup LoadStringFromFile fails when file is open in another process

为了检查数据库(SQL Anywhere)何时启动并准备好接收请求,我将数据库消息 window 输出到日志(文本)文件,然后尝试使用 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;

有什么方法可以读取正在使用的文件或其他方法吗?

使用 TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone).

在 Inno Setup 的 Unicode 版本(Inno Setup 6 的唯一版本)中,由于 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;

代码基于TLama's code posted in .

生成数据库服务器时,使用专为此目的设计的 dbspawn 实用程序。您生成 dbspawn 以及您想要 运行 的 dbeng/dbsrv 命令,它会为您启动服务器。 dbspawn 实用程序不会 return 直到数据库服务器启动,运行 并且准备好接受请求,因此不需要猜测,也不需要读取控制台日志文件。

我不知道 SQL 是什么版本 运行ning,但这是 documentation for v17。其他版本应该都一样。