如何让Inno Setup在安装过程中解压已安装的文件(全部作为一个安装过程的一部分)

19
为了节省带宽/空间并防止意外干扰,数据库产品的安装文件(称其为Ajax)已被压缩(将该文件称为"AJAX_Install_Files.ZIP")。我想让Inno-Setup "安装"(即复制)AJAX_Install_Files.ZIP文件到目标位置,然后解压缩文件到与.ZIP文件相同的文件夹中。随后,Inno Setup会触发一个程序来实际运行"Ajax"产品的安装。
我查看了Inno Setup网站的文档、常见问题和知识库,除了编写Pascal脚本(代码)之外似乎没有其他可行方案,这是正确的吗?还是有其他替代方案?

不需要。Innosetup本身已经压缩了这些文件,双重压缩这些文件没有任何好处。这只会使安装过程变慢,需要更多的代码和磁盘空间,在安装过程中增加故障模式。 - MSalters
5个回答

27

你可以使用一个外部命令行工具来解压缩你的归档文件,例如在这里。将它放在你的 [Files] 部分中:

[Files]
Source: "UNZIP.EXE"; DestDir: "{tmp}"; Flags: deleteafterinstall
然后在你的 [Run] 部分调用它,像这样:
[Run]
Filename: "{tmp}\UNZIP.EXE"; Parameters: "{tmp}\ZipFile.ZIP -d C:\TargetDir"

(您可能希望从脚本变量中获取目标目录,因此还需要进行一些更多的工作)


有没有办法隐藏屏幕上显示的日志? - Talysson de Castro
2
@TalyssondeCastro 使用 Flags: runhidden - Martin Prikryl
2
正确,但是我需要在 .zip 和目标目录周围加上引号。为此,您必须用另一组引号进行转义,使其如下所示:""{tmp}\ZipFile.ZIP" -d "C:\TargetDir" - Bert Haddad
1
请记住,在解压缩时应添加“-o”标志。否则,如果需要覆盖文件,则此过程将无限期挂起。 - Andy

14

您可以使用shell Folder.CopyHere方法来提取ZIP文件。

const
  SHCONTCH_NOPROGRESSBOX = 4;
  SHCONTCH_RESPONDYESTOALL = 16;

procedure UnZip(ZipPath, TargetPath: string); 
var
  Shell: Variant;
  ZipFile: Variant;
  TargetFolder: Variant;
begin
  Shell := CreateOleObject('Shell.Application');

  ZipFile := Shell.NameSpace(ZipPath);
  if VarIsClear(ZipFile) then
    RaiseException(
      Format('ZIP file "%s" does not exist or cannot be opened', [ZipPath]));

  TargetFolder := Shell.NameSpace(TargetPath);
  if VarIsClear(TargetFolder) then
    RaiseException(Format('Target path "%s" does not exist', [TargetPath]));

  TargetFolder.CopyHere(
    ZipFile.Items, SHCONTCH_NOPROGRESSBOX or SHCONTCH_RESPONDYESTOALL);
end;

请注意,标志SHCONTCH_NOPROGRESSBOXSHCONTCH_RESPONDYESTOALL仅适用于Windows Vista及更高版本。


有关仅提取某些文件的示例,请参见:
如何让Inno Setup仅解压缩单个文件?


2
虽然Slick很好用,但如果压缩文件太大,它会锁定用户界面。不过,可以将脚本打包为.ps1文件,并以与此示例启动7zip相同的方式启动它:https://gist.github.com/jakoch/33ac13800c17eddb2dd4 - Dan

8

我回答了一个非常类似的问题,其中一些细节也适用于此。

我想问一下为什么你需要一个ZIP文件来存储内容?我个人会将未压缩的文件放入安装包中。然后我会有两个[category]条目,一个用于应用程序,另一个用于数据。默认都选中。

这将允许用户在以后需要时安装一组新的数据。

如果你真的想要一个ZIP文件,并且想要保持简单,你可以在同一个安装包中同时提供ZIP文件和未压缩的文件。

更新:

默认情况下,放置在setup.exe中的文件是压缩的

你也可以将文件提取到临时位置,这样你就可以运行你的安装应用程序,然后将它们删除。

[Files]
Source: "Install1.SQL"; DestDir: "{tmp}"; Flags:deleteafterinstall;
Source: "Install2.SQL"; DestDir: "{tmp}"; Flags:deleteafterinstall;

5
为什么要压缩文件 - 因为这是我收到的文件格式,我认为使用一个ZIP文件比使用2000多个文件更容易处理。这个ZIP文件是我试图自动化安装的多个程序中的一个程序的安装和数据文件。一旦我把文件“安装”(实际上是复制)到目标机器上,我就会启动数据库安装程序,并使用另一个自动化工具来自动安装它。因此,最终我需要重复以上过程多次(> 2)。 - Dan Aquinas
如果我不部署这个zip文件呢? - none

1
你可以创建无声自解压缩(SFX)归档,例如这里描述的如何创建SFX归档所需内容,并编写Pascal代码来运行它,就像这样(Inno Setup 6.0.2脚本):
[Tasks]
Name: "intallSenselockDriver"; Description: "Install Senselock driver."; GroupDescription: "Install the necessary software:";

[Code]
function ExecTmpFile(FileName: String): Boolean;
var
  ResultCode: Integer;
begin
  if not Exec(ExpandConstant('{tmp}\' + FileName), '', '', SW_SHOWNORMAL, ewWaitUntilTerminated, ResultCode)
  then
    begin
      MsgBox('Other installer failed to run!' + #13#10 + SysErrorMessage(ResultCode), mbError, MB_OK);
      Result := False;
    end
  else
    Result := True;
end;

procedure RunOtherInstallerSFX(ArchiveName: String; ExePath: String);
begin
  ExtractTemporaryFile(ArchiveName);
  ExecTmpFile(ArchiveName);
  ExecTmpFile(ExePath);
end;

function PrepareToInstall(var NeedsRestart: Boolean): String;
begin
  if WizardIsTaskSelected('intallSenselockDriver') then
    RunOtherInstallerSFX('1_senselock_windows_3.1.0.0.exe', '1_senselock_windows_3.1.0.0\InstWiz3.exe');

  Result := '';
end;

它对我来说完美地工作了。


-1

使用双引号对我有用。 单引号不起作用。

[Files]
Source: "unzip.exe"; DestDir: "{userappdata}\{#MyAppName}\{#InputFolderName}"; Flags: ignoreversion 

[Run]
Filename: "{userappdata}\{#MyAppName}\{#InputFolderName}\unzip.exe"; Parameters: " ""{userappdata}\{#MyAppName}\{#InputFolderName}\ZIPFILENAME.zip""  -d  ""{userappdata}\{#MyAppName}\{#InputFolderName}""  ";  Flags: runascurrentuser

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接