Inno Setup - How to add cancel button to decompressing page?

前端 未结 2 741
误落风尘
误落风尘 2020-12-01 23:23

I am using this code: How to add .arc decompression to Inno Setup? (answer of Martin Prikryl). I want to add a cancel button at decompressing page and active this page for o

相关标签:
2条回答
  • 2020-12-01 23:46

    All you need is this http://fileforums.com/showthread.php?t=96619

    This program have the latest compatibility with inno setup and also supports Password based file with multiple extensions.

    0 讨论(0)
  • 2020-12-01 23:55

    I have reimplemented the solution from How to add .arc decompression to Inno Setup? using unarc.dll (from FreeArc+InnoSetup package ISFreeArcExtract v.4.0.rar).

    It greatly simplifies the code and also makes it easier to add the ability to cancel the decompression.


    #define ArcArchive "test.arc"
    
    [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;
      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
        ArcTotalSize := Int1;
        Log(Format('Total size of files to be extracted is %d MB', [ArcTotalSize]));
      end
        else
      if What = 'write' then
      begin
        if ArcTotalSize > 0 then
        begin
          ArcProgressPage.SetProgress(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(ArcExtracted, ArcTotalSize);
        end;
      end;
    
      if ArcCancel then Result := ArcCancelCode
        else Result := 0;
    end;
    
    function FreeArcCmd(
      Cmd1, Cmd2, Cmd3, Cmd4, Cmd5, Cmd6, Cmd7, Cmd8, Cmd9, Cmd10: string): Integer;
    begin
      ArcCancel := False;
      try
        Result :=
          FreeArcExtract(
            CreateCallback(@FreeArcCallback),
            GetStringAsUtf8(Cmd1), GetStringAsUtf8(Cmd2), GetStringAsUtf8(Cmd3),
            GetStringAsUtf8(Cmd4), GetStringAsUtf8(Cmd5), GetStringAsUtf8(Cmd6),
            GetStringAsUtf8(Cmd7), GetStringAsUtf8(Cmd8), GetStringAsUtf8(Cmd9),
            GetStringAsUtf8(Cmd10));
    
        Log(Format('Arc command "%s" result %d', [Cmd1, Result]));
      except
        Result := -63;
      end;
    end;
    
    function UnPackArchive(ArchivePath: string; DestPath: string): Integer;
    begin
      { Find out length of files to be extracted - origsize }
      Result := FreeArcCmd('l', '--', ArchivePath, '', '', '', '', '', '', '');
    
      if Result = 0 then
      begin
        { Actually extract }
        Result :=
          FreeArcCmd('x', '-o+', '-dp' + DestPath, '-w' + DestPath, '--', ArchivePath,
                     '', '', '', '');
      end;
    end;
    
    procedure UnpackCancelButtonClick(Sender: TObject);
    begin
      ArcCancel := True;
    end;
    
    procedure ExtractArc;
    var
      ArcArchivePath: string;
      UnpackResult: Integer;
      PrevCancelButtonClick: TNotifyEvent;
      Error: string;
    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;
    
        ArcArchivePath := ExpandConstant('{src}\{#ArcArchive}');
        Log(Format('Arc extraction starting - %s', [ArcArchivePath]));
    
        ArcExtracted := 0;
        UnpackResult := UnPackArchive(ArcArchivePath, ExpandConstant('{app}'));
    
        if UnpackResult <> 0 then
        begin
          if ArcCancel then
          begin
            Error := 'Extraction cancelled';
          end
            else
          begin
            Error := Format('Extraction failed with code %d', [UnpackResult]);
          end;
    
          MsgBox(Error, mbError, MB_OK);
        end;
      finally
        Log('Arc extraction cleanup');
        ArcProgressPage.Hide;
        WizardForm.CancelButton.OnClick := PrevCancelButtonClick;
      end;
    end;
    
    procedure CurStepChanged(CurStep: TSetupStep);
    begin
      if CurStep = ssPostInstall then
      begin
        ExtractArc;
      end;
    end;
    

    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.



    The code extracts a separate .arc file. If you want to embed the archive to the installer, you can use

    [Files]
    Source: {#ArcArchive}; DestDir: "{tmp}"; Flags: nocompression deleteafterinstall
    

    And extract the archive from the {tmp}:

    ArcArchivePath := ExpandConstant('{tmp}\{#ArcArchive}');
    

    Note that the unarc.dll from ISFreeArcExtract v.4.0.rar does not seem to support password protected archives. The version from ISFreeArcExtract v.4.2.rar does, but I'm not aware of trustworthy download link.


    If you want to extract multiple archives, see Inno Setup - How to add multiple arc files to decompress?

    0 讨论(0)
提交回复
热议问题