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

Posted

技术标签:

【中文标题】当文件在另一个进程中打开时,Inno Setup LoadStringFromFile 失败【英文标题】:Inno Setup LoadStringFromFile fails when file is open in another process 【发布时间】:2016-12-09 10:47:28 【问题描述】:

要检查数据库 (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;

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

【问题讨论】:

【参考方案1】:

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

我不知道您运行的是哪个版本的 SQL Anywhere,但这里是 documentation for v17。在任何其他版本中都应该是相同的。

【讨论】:

我已经接受了 Martin Prikryl 的回答,因为它直接解决了我提出的编码问题,并且对于寻找这个问题的答案的其他人来说是最相关的。但是,我实际上已将您的答案用于我的解决方案。这正是我在这种特殊情况下所需要的。我的解决方案是在不知道这个方便的小实用程序的情况下提出的一种解决方法。谢谢。赞成。【参考方案2】:

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

在 Inno Setup 的 Unicode 版本(Inno Setup 6 的唯一版本)中,由于类的接口不好,它的使用很棘手。

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 发布在Read bytes from file at desired position with Inno Setup。

【讨论】:

我接受这个作为答案,因为它直接回答了我提出的问题。然而,在这种情况下,Graeme Perrow 的回答实际上是一种更加优雅和简单的方式来判断数据库何时启动并在 SQL Anywhere 中接受请求。

以上是关于当文件在另一个进程中打开时,Inno Setup LoadStringFromFile 失败的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 inno setup 结束进程?

卸载失败,因为程序正在运行。如何在尝试删除之前让 Inno Setup 检查正在运行的进程?

通过Windows Vista / 7上的Inno Setup将文件安装到原始用户的My Docs文件夹

inno setup打包软件学习

在 Inno Setup 中使用“taskkill /f /im”在(重新)安装之前终止进程

在移动设备中打开时将链接转换为幻灯片过渡