Inno Setup-如何添加多个Arc文件进行解压缩? [英] Inno Setup - How to add multiple arc files to decompress?

查看:82
本文介绍了Inno Setup-如何添加多个Arc文件进行解压缩?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用以下代码: Inno设置-如何在解压缩页面上添加取消按钮?(Martin Prikryl的答案)是使用Inno Setup解压缩弧文件。

I am using this code: Inno Setup - How to add cancel button to decompressing page? (answer of Martin Prikryl) to decompress an arc file with Inno Setup.

我想解压缩多个arc文件以从组件选择中安装文件(例如)。但仍会在所有提取的总体进度条上显示。整个有可能吗?

I want to have the possibility of decompress more than one arc file to install files from components selection (for example). But still show on overall progress bar for all extractions. whole Is this possible?

推荐答案

这是我对 Inno设置-如何在解压缩页面上添加取消按钮?

前提条件相同,请参考其他答案。

Prerequisities are the same, refer to the other answer.

ExtractArc 中,为要提取的每个档案调用 AddArchive

In the ExtractArc, call AddArchive for each archive you want to extract.

[Files]
Source: unarc.dll; Flags: dontcopy

[Code]

const
  ArcCancelCode = -10;

function FreeArcExtract(
  Callback: LongWord;
  Cmd1, Cmd2, Cmd3, Cmd4, Cmd5, Cmd6, Cmd7, Cmd8, Cmd9, Cmd10: PAnsiChar): Integer;
  external 'FreeArcExtract@files:unarc.dll cdecl';

const
  CP_UTF8 = 65001;

function WideCharToMultiByte(CodePage: UINT; dwFlags: DWORD;
  lpWideCharStr: string; cchWideChar: Integer; lpMultiByteStr: AnsiString;
  cchMultiByte: Integer; lpDefaultCharFake: Integer;
  lpUsedDefaultCharFake: Integer): Integer;
  external 'WideCharToMultiByte@kernel32.dll stdcall';

function GetStringAsUtf8(S: string): AnsiString;
var
  Len: Integer;
begin
  Len := WideCharToMultiByte(CP_UTF8, 0, S, Length(S), Result, 0, 0, 0);
  SetLength(Result, Len);
  WideCharToMultiByte(CP_UTF8, 0, S, Length(S), Result, Len, 0, 0);
end;

var
  ArcTotalSize: Integer;
  ArcTotalExtracted: Integer;
  ArcExtracted: Integer;
  ArcCancel: Boolean;
  ArcProgressPage: TOutputProgressWizardPage;

function FreeArcCallback(
  AWhat: PAnsiChar; Int1, Int2: Integer; Str: PAnsiChar): Integer;
var
  What: string;
begin
  What := AWhat;
  if What = 'origsize' then
  begin
    Log(Format('Adding archive with files with total size %d MB', [Int1]));
    ArcTotalSize := ArcTotalSize + Int1;
  end
    else
  if What = 'write' then
  begin
    if ArcTotalSize > 0 then
    begin
      ArcProgressPage.SetProgress(ArcTotalExtracted + Int1, ArcTotalSize);
    end;
    ArcExtracted := Int1;
  end
    else
  begin
    { Just to pump message queue more often (particularly for 'read' callbacks), }
    { to get more smooth progress bar }
    if (ArcExtracted > 0) and (ArcTotalSize > 0) then
    begin
      ArcProgressPage.SetProgress(ArcTotalExtracted + ArcExtracted, ArcTotalSize);
    end;
  end;

  if ArcCancel then Result := ArcCancelCode
    else Result := 0;
end;

procedure FreeArcCmd(
  Cmd1, Cmd2, Cmd3, Cmd4, Cmd5, Cmd6, Cmd7, Cmd8, Cmd9, Cmd10: string);
var
  ArcResult: Integer;
begin
  ArcCancel := False;
  ArcResult :=
    FreeArcExtract(
      CreateCallback(@FreeArcCallback),
      GetStringAsUtf8(Cmd1), GetStringAsUtf8(Cmd2), GetStringAsUtf8(Cmd3),
      GetStringAsUtf8(Cmd4), GetStringAsUtf8(Cmd5), GetStringAsUtf8(Cmd6),
      GetStringAsUtf8(Cmd7), GetStringAsUtf8(Cmd8), GetStringAsUtf8(Cmd9),
      GetStringAsUtf8(Cmd10));

  if ArcCancel then
  begin
    RaiseException('Extraction cancelled');
  end
    else
  if ArcResult <> 0 then
  begin
    RaiseException(Format('Extraction failed with code %d', [ArcResult]));
  end;
end;

var
  ArcArchives: array of string;

procedure AddArchive(ArchivePath: string);
begin
  SetArrayLength(ArcArchives, GetArrayLength(ArcArchives) + 1); 
  ArcArchives[GetArrayLength(ArcArchives) - 1] := ArchivePath;
  FreeArcCmd('l', '--', ArchivePath, '', '', '', '', '', '', '');
end;

procedure UnPackArchives(DestPath: string);
var
  I: Integer;
  ArchivePath: string;
begin
  Log(Format('Total size of files to be extracted is %d MB', [ArcTotalSize]));

  ArcTotalExtracted := 0;
  for I := 0 to GetArrayLength(ArcArchives) - 1 do
  begin
    ArcExtracted := 0;
    ArchivePath := ArcArchives[I];
    Log(Format('Extracting %s', [ArchivePath]));
    FreeArcCmd('x', '-o+', '-dp' + DestPath, '-w' + DestPath, '--', ArchivePath,
               '', '', '', '');
    ArcTotalExtracted := ArcTotalExtracted + ArcExtracted;
  end;
end;

procedure UnpackCancelButtonClick(Sender: TObject);
begin
  ArcCancel := True;
end;

procedure ExtractArc;
var
  PrevCancelButtonClick: TNotifyEvent;
begin
  ArcProgressPage :=
    CreateOutputProgressPage('Decompression', 'Decompressing archive...');
  ArcProgressPage.SetProgress(0, 100);
  ArcProgressPage.Show;
  try
    WizardForm.CancelButton.Visible := True;
    WizardForm.CancelButton.Enabled := True;
    PrevCancelButtonClick := WizardForm.CancelButton.OnClick;
    WizardForm.CancelButton.OnClick := @UnpackCancelButtonClick;

    try
      AddArchive(ExpandConstant('{src}\test1.arc'));
      AddArchive(ExpandConstant('{src}\test2.arc'));

      Log('Arc extraction starting');
      UnPackArchives(ExpandConstant('{app}'));
    except
      MsgBox(GetExceptionMessage(), mbError, MB_OK);
    end;
  finally
    Log('Arc extraction done');
    ArcProgressPage.Hide;
    WizardForm.CancelButton.OnClick := PrevCancelButtonClick;
  end;
end;

procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssPostInstall then
  begin
    ExtractArc;
  end;
end;

对于 CreateCallback 函数,您需要Inno Setup6。如果您对Inno Setup 5不满意,可以使用<$ c来自 InnoTools InnoCallback 库的$ c> WrapCallback 函数。

For CreateCallback function, you need Inno Setup 6. If you are stuck with Inno Setup 5, you can use WrapCallback function from InnoTools InnoCallback library.

这篇关于Inno Setup-如何添加多个Arc文件进行解压缩?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆