3

When running new releases of my installer I would like to make a backup of an existing installation by adding files into a ZIP archive.

Currently, I am able to make a backup of an existing installation by coping the files to my Backup destination. A simplified version of the method I use is as follows:

[Files]
; Copy the contents of Bin folder to Backup folder. Skip if files don’t exist. 
Source: {app}\Bin\*;  DestDir: {app}\Backup\; \
    Flags: createallsubdirs external recursesubdirs uninsneveruninstall skipifsourcedoesntexist;

I would appreciate any ideas how I can zip instead?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Lars
  • 1,428
  • 1
  • 13
  • 22
  • 1
    I think e.g. 7-zip, or zlib DLLs could be used to pack the files (if it's possible to translate their function exports into Inno Setup). Or, you can write a very simple single purpose DLL by yourself (as I've seen you're a native language programmer). – TLama Nov 07 '13 at 09:39

3 Answers3

2

you may want to check out LOGAN ISSI : http://members.home.nl/albartus/inno/index.html there are some utils bundled with it.

Another method would be to include a batch file which will carry out the backup steps and then get it to remove itself once complete.

checkout this thread: Batch script to zip all the files without the parent folder

however due to licensing you are not allowed to bundle rar.dll with your app so just apply this method but use a package/dll which can be redistributed.

If you can use VBScript to code a simple wrapper you can also make use of windows built in zip compression.

See how you: Can Windows' built-in ZIP compression be scripted?

Community
  • 1
  • 1
majika
  • 21
  • 2
2

I used TLama's suggestion and created my own DLL in Delphi (XE3) that zips a folder.

library MyZipLib;
uses
  Winapi.Windows,
  System.SysUtils,
  System.Zip;

{$R *.res}

function ZipCompressFolder(SourcePath, DestinationPath, ArchiveName : PChar): boolean; stdcall;
begin
  //If source folder does not exist then exit without error.
  if not DirectoryExists(SourcePath) then
  begin
    result := true;
    exit;
  end;

  try
    result := false;

    //Make sure destination path exists
    ForceDirectories(DestinationPath);
    TZipFile.ZipDirectoryContents(IncludeTrailingPathDelimiter(DestinationPath) + ArchiveName, SourcePath);
    result := true;
  except
    on E : Exception do MessageBox(0, PChar('Error calling function ZipCompressFolder@MyZipLib.dll with message: ' + E.Message + #13#10 + 'Source: ' + SourcePath + #13#10 + 'Dest: ' + DestinationPath+ #13#10 + 'Archive: ' + ArchiveName), 'MyZipLib.dll Error', MB_OK);
  end;
end;

exports ZipCompressFolder;
begin
end.
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Lars
  • 1,428
  • 1
  • 13
  • 22
1

If you know that you are installing on a machine that has .NET 4.5 and newer (i.e. on Windows 8 and newer), you can use PowerShell and .NET 4.5 ZipFile class from CurStepChanged(ssInstall) event function.

[Code]

procedure CurStepChanged(CurStep: TSetupStep);
var
  Command, AppPath, ZipName, ZipTmpPath, ZipPath: string;
  ResultCode: Integer;
begin
  if CurStep = ssInstall then
  begin
    AppPath := ExpandConstant('{app}');
    if not DirExists(AppPath) then
    begin
      Log(Format('Application path "%s" does not exist, ' +
        ' probably fresh install, not backing up', [AppPath]));
    end
      else
    begin
      ZipName := 'backup.zip';
      ZipTmpPath := ExpandConstant('{tmp}') + '\' + ZipName;  
      ZipPath := AppPath + '\' + ZipName;  
      if FileExists(ZipPath) then
      begin
        if DeleteFile(ZipPath) then
          Log(Format('Archive ZIP "%s" exists, deleted', [ZipPath]))
        else
          RaiseException(Format(
            'Archive ZIP "%s" exists, and it could not be deleted', [ZipPath]));
      end;

      Log(Format('Archiving application folder "%s" to temporary "%s"', [
        AppPath, ZipTmpPath]));
      Command :=
        'Add-Type -Assembly System.IO.Compression.FileSystem ; ' +
        '[System.IO.Compression.ZipFile]::CreateFromDirectory(''' +
          AppPath + ''', ''' + ZipTmpPath +''')';
      if Exec('powershell', '-ExecutionPolicy Bypass -command "' + Command + '"',
           '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and
         (ResultCode = 0) then
      begin
        Log(Format('Application folder "%s" archived to temporary "%s"', [
          AppPath, ZipTmpPath]));
      end
        else
      begin
        RaiseException(Format('Error archiving application folder "%s" "%s"', [
          AppPath, ZipTmpPath]));
      end;

      if FileCopy(ZipTmpPath, ZipPath, False) then
        Log(Format('Copied "%s" to "%s"', [ZipTmpPath, ZipPath]))
      else
        RaiseException(Format('Error copying "%s" to "%s"', [
          ZipTmpPath, ZipPath]));
    end;
  end;
end;

If you need to support even older versions of Windows, you might do with Shell.Application class. Though I was not able to make it create a ZIP file, only add to one. A solution might be to add an empty ZIP file to the installer, and add to it.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992