Inno Setup - Delete old/obsolete files on update

微笑、不失礼 提交于 2020-03-20 08:00:54

问题


So, I realize that this question has been asked before. In fact I read through a good 10 of them before writing this, but none of them have a applicable solution and I'm hoping that nowadays someone has found something.

The problem: My program is build with a script, creating all final files in a single folder. Those files are included in inno like this:

[Files]
Source: "build\exe.win-amd64-3.6\*"; Excludes: "*.key, *.log"; DestDir: "{app}"; \
    Flags: ignoreversion recursesubdirs createallsubdirs

The application has been out there for a few months with different updates. There is no record anymore of old files, though it could be painstakingly re-assembled as we do have version control and I could build the old installers again.

From what I understand, you're meant to use the InstallDelete section to get rid of old files - however you are not meant to use wildcards and there is also no Excludes section to safeguard the single folder we have that may contain user data they may want to keep.

So, how do I get rid of old files? The application is 100 MB and a current user may have 300+ MB of old files that are no longer necessary, I'd love to clean that up.

TL;DR: I want the installer to either overwrite or delete all files in the application directory, except for one folder which contains user data.


回答1:


The easiest solution is to delete all files in the installation folder before the installation.

As you know, you can use [InstallDelete] section for that. But that does not allow you to exclude the "data" folder.

You can code that Pascal Scripting instead. See Inno Setup - Delete whole application folder except for data subdirectory. You can call the DelTreeExceptSavesDir function from my answer to the that question from CurStepChanged(ssInstall) event function:

procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssInstall then
  begin
    DelTreeExceptSavesDir(WizardDirValue); 
  end;
end;

If you really want to delete only obsolete files, to avoid deleting and re-creating existing files (what's not your case, as you are using ignoreversion flag anyway), you can use preprocessor to generate a list of files to be installed for the Pascal Scripting and use that to delete only really obsolete files.

#pragma parseroption -p-

#define FileEntry(DestDir) \
    "  FilesNotToBeDeleted.Add('" + LowerCase(DestDir) + "');\n"

#define ProcessFile(Source, Dest, FindResult, FindHandle) \
    FindResult \
        ? \
            Local[0] = FindGetFileName(FindHandle), \
            Local[1] = Source + "\\" + Local[0], \
            Local[2] = Dest + "\\" + Local[0], \
            (Local[0] != "." && Local[0] != ".." \
                ? FileEntry(Local[2]) + \
                  (DirExists(Local[1]) ? ProcessFolder(Local[1], Local[2]) : "") \
                : "") + \
            ProcessFile(Source, Dest, FindNext(FindHandle), FindHandle) \
        : \
            ""

#define ProcessFolder(Source, Dest) \
    Local[0] = FindFirst(Source + "\\*", faAnyFile), \
    ProcessFile(Source, Dest, Local[0], Local[0])

#pragma parseroption -p+

[Code]

var
  FilesNotToBeDeleted: TStringList;

function InitializeSetup(): Boolean;
begin
  FilesNotToBeDeleted := TStringList.Create;
  FilesNotToBeDeleted.Add('\data');
  {#Trim(ProcessFolder('build\exe.win-amd64-3.6', ''))}
  FilesNotToBeDeleted.Sorted := True;

  Result := True;
end;

procedure DeleteObsoleteFiles(Path: string; RelativePath: string);
var
  FindRec: TFindRec;
  FilePath: string;
  FileRelativePath: string;
begin
  if FindFirst(Path + '\*', FindRec) then
  begin
    try
      repeat
        if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
        begin
          FilePath := Path + '\' + FindRec.Name;
          FileRelativePath := RelativePath + '\' + FindRec.Name;
          if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then
          begin
            DeleteObsoleteFiles(FilePath, FileRelativePath);
          end;

          if FilesNotToBeDeleted.IndexOf(Lowercase(FileRelativePath)) < 0 then
          begin
            if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY <> 0 then
            begin
              if RemoveDir(FilePath) then
              begin
                Log(Format('Deleted obsolete directory %s', [FilePath]));
              end
                else
              begin
                Log(Format('Failed to delete obsolete directory %s', [FilePath]));
              end;
            end
              else
            begin
              if DeleteFile(FilePath) then
              begin
                Log(Format('Deleted obsolete file %s', [FilePath]));
              end
                else
              begin
                Log(Format('Failed to delete obsolete file %s', [FilePath]));
              end;
            end;
          end;
        end;
      until not FindNext(FindRec);
    finally
      FindClose(FindRec);
    end;
  end
    else
  begin
    Log(Format('Failed to list %s', [Path]));
  end;
end;

procedure CurStepChanged(CurStep: TSetupStep);
begin
  if CurStep = ssInstall then
  begin
    Log('Looking for obsolete files...');
    DeleteObsoleteFiles(WizardDirValue, '');
  end;
end;

For other options, see Inno Setup: Removing files installed by previous version.



来源:https://stackoverflow.com/questions/51130059/inno-setup-delete-old-obsolete-files-on-update

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!