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.