如何将安装程序复制到临时文件,然后 运行 它?

How can I copy the installer to the temp file and then run it?

我正在尝试将安装程序复制到临时文件夹,然后从该位置 运行 复制它。

这就是我想要做的,但到目前为止无济于事。

FileCopy(ExpandConstant('{srcexe}'), ExpandConstant('{tmp}\Setup.exe'), True);
Exec(ExpandConstant('{tmp}\Setup.exe'), '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode)

如何将安装程序复制到临时文件,然后从代码部分运行复制它?

不知道为什么,但是有一个明确的检查可以防止 FileCopy function 复制安装程序本身。

看到一个PathCompare check in FileCopy branch of CmnFunc2Proc in ScriptFunc_R.pas:

end else if Proc.Name = 'FILECOPY' then begin
  ExistingFilename := Stack.GetString(PStart-1);
  if PathCompare(ExistingFilename, SetupLdrOriginalFilename) <> 0 then
    Stack.SetBool(PStart, CopyFileRedir(ScriptFuncDisableFsRedir,
      ExistingFilename, Stack.GetString(PStart-2), Stack.GetBool(PStart-3)))
  else
    Stack.SetBool(PStart, False);

我不知道这是什么原因,但可能有一些。所以当心,你可能正在做一些安装程序不喜欢的事情。


你当然可以通过调用 Windows copy command:

来解决这个问题
Exec(
  ExpandConstant('{cmd}'),
  Format('/C copy "%s" "%s"', [ExpandConstant('{srcexe}'), ExpandConstant('{tmp}\Setup.exe')]),
  '', SW_HIDE, ewWaitUntilTerminated, ResultCode);

或者您可以使用 TFileStream class:

实现替换功能
function FileCopyUnrestricted(const ExistingFile, NewFile: String): Boolean;
var
  Buffer: string;
  Stream: TFileStream;
  Size: Integer;
begin
  Result := True;
  try
    Stream := TFileStream.Create(ExistingFile, fmOpenRead or fmShareDenyNone);
    try
      Size := Stream.Size;
      SetLength(Buffer, Size div 2 + 1);
      Stream.ReadBuffer(Buffer, Size);
    finally
      Stream.Free;
    end;
  except
    Result := False;
  end;

  if Result then
  begin
    try
      Stream := TFileStream.Create(NewFile, fmCreate);
      try
        Stream.WriteBuffer(Buffer, Size);
      finally
        Stream.Free;
      end;
    except
      Result := False;
    end;
  end;
end;

这是将整个文件加载到内存的低效实现。如果您的安装程序很大,您将不得不改进代码以分块复制文件。

该代码适用于 Inno Setup 的 Unicode 版本(Inno Setup 6 的唯一版本)。