Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
502 views
in Technique[技术] by (71.8m points)

pascalscript - Inno Setup - Delete whole application folder except for data subdirectory

I usually have no problem backing up savegames, but for this particular game, I use FreeArc, since the game is very large, so Inno Setup doesn't really know which files to delete. With FreeArc, you need to use

[UninstallDelete]
Type: files; Name: "{app}"

But this particular game stores savegames in {app}datasave. I need a function to move that folder somewhere, uninstall the game, and then move it back.

Here's my code:

procedure DirectoryCopy(SourcePath, DestPath: string);
var
  FindRec: TFindRec;
  SourceFilePath: string;
  DestFilePath: string;
begin
  if FindFirst(SourcePath + '*', FindRec) then
  begin
    try
      repeat
        if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
        begin
          SourceFilePath := SourcePath + '' + FindRec.Name;
          DestFilePath := DestPath + '' + FindRec.Name;
          if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
          begin
            if FileCopy(SourceFilePath, DestFilePath, False) then
            begin
              Log(Format('Copied %s to %s', [SourceFilePath, DestFilePath]));
            end
              else
            begin
              Log(Format('Failed to copy %s to %s', [SourceFilePath, DestFilePath]));
            end;
          end
            else
          begin
            if CreateDir(DestFilePath) then
            begin
              Log(Format('Created %s', [DestFilePath]));
              DirectoryCopy(SourceFilePath, DestFilePath);
            end
              else
            begin
              Log(Format('Failed to create %s', [DestFilePath]));
            end;
          end;
        end;
      until not FindNext(FindRec);
    finally
      FindClose(FindRec);
    end;
  end
    else
  begin
    Log(Format('Failed to list %s', [SourcePath]));
  end;
end;

procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
Begin
  if (CurUninstallStep = usUninstall) and
     DirExists(ExpandConstant('{app}dataSAVE')) then
  begin
    if MsgBox('Do you want to delete all save games?',
         mbConfirmation, MB_YESNO) = IDYES then
      begin
        DelTree(ExpandConstant('{app}'), True, True, True);
      end
    else
      begin
        DirectoryCopy(ExpandConstant('{app}dataSAVE'), ExpandConstant('{app}SAVE'));
        Deltree(ExpandConstant('{app}data'), True, True, True);
        DirectoryCopy(ExpandConstant('{app}SAVE'), ExpandConstant('{app}dataSAVE'));
      end
  end;
End;

And here's the log:

2016-04-08 10:16:02.420   Log opened. (Time zone: UTC+04:00)
2016-04-08 10:16:02.421   Setup version: Inno Setup version 5.5.6 (u)
2016-04-08 10:16:02.421   Original Uninstall EXE: C:GamesMyAppunins001.exe
2016-04-08 10:16:02.421   Uninstall DAT: C:GamesMyAppunins001.dat
2016-04-08 10:16:02.421   Uninstall command line: /SECONDPHASE="C:GamesMyAppunins001.exe" /FIRSTPHASEWND=$B5111C /log=C:setup.log
2016-04-08 10:16:02.421   Windows version: 6.1.7601 SP1  (NT platform: Yes)
2016-04-08 10:16:02.421   64-bit Windows: Yes
2016-04-08 10:16:02.421   Processor architecture: x64
2016-04-08 10:16:02.421   User privileges: Administrative
2016-04-08 10:16:02.421   64-bit install mode: No
2016-04-08 10:16:02.422   Created temporary directory: C:UsersGeorgeAppDataLocalTempis-GSI4R.tmp
2016-04-08 10:16:02.440   Message box (Yes/No):
                          Are you sure you want to completely remove MyApp and all of its components?
2016-04-08 10:16:04.014   User chose Yes.
2016-04-08 10:16:04.031   Message box (Yes/No):
                          Do you want to delete all save games?
2016-04-08 10:16:04.790   User chose No.
2016-04-08 10:16:04.791   Failed to create C:GamesMyAppSAVEscores
2016-04-08 10:16:04.805   Failed to list C:GamesMyAppSAVE
2016-04-08 10:16:04.805   Starting the uninstallation process.
2016-04-08 10:16:04.806   Deleting Uninstall data files.
2016-04-08 10:16:05.326   Uninstallation process succeeded.
2016-04-08 10:16:05.326   Removed all? Yes
2016-04-08 10:16:05.326   Need to restart Windows? No
2016-04-08 10:16:05.814   Message box (OK):
                          MyApp was successfully removed from your computer.
2016-04-08 10:16:06.678   User chose OK.
2016-04-08 10:16:06.679   Log closed.
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Isn't it an overkill to copy the saves away and then back?

Once you already have a code to iterate a directory tree, iterate it to delete the files, except the "save" folder.

The below code does all the delete work (in either mode), so you need to remove the [UninstallDelete] section.

procedure DelTreeExceptSavesDir(Path: string);
var
  FindRec: TFindRec;
  FilePath: string;
begin
  if FindFirst(Path + '*', FindRec) then
  begin
    try
      repeat
        if (FindRec.Name <> '.') and (FindRec.Name <> '..') then
        begin
          FilePath := Path + '' + FindRec.Name;
          if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
          begin
            if DeleteFile(FilePath) then
            begin
              Log(Format('Deleted file %s', [FilePath]));
            end
              else
            begin
              Log(Format('Failed to delete file %s', [FilePath]));
            end;
          end
            else
          begin
            if CompareText(FindRec.Name, 'save') = 0 then
            begin
              Log(Format('Keeping directory %s', [FilePath]));
            end
              else
            begin
              DelTreeExceptSavesDir(FilePath);

              if RemoveDir(FilePath) then
              begin
                Log(Format('Deleted directory %s', [FilePath]));
              end
                else
              begin
                Log(Format('Failed to delete directory %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 CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var
  SavePath: string;
  AppPath: string;
begin
  SavePath := ExpandConstant('{app}dataSAVE');

  if CurUninstallStep = usUninstall then
  begin
    AppPath := ExpandConstant('{app}')

    if (not DirExists(SavePath)) or
       (MsgBox('Do you want to delete all save games?',
          mbConfirmation, MB_YESNO) = IDYES) then
    begin
      Log(Format('Deleting application folder %s', [AppPath]));
      DelTree(AppPath, True, True, True);
    end
      else
    begin
      Log(Format('Deleting application folder %s except saves', [AppPath]));
      DelTreeExceptSavesDir(AppPath);
    end;
    Log('Delete done');
  end
end;

Though, wouldn't it be easier to list directories to delete in the [UninstallDelete] section? There cannot be that many folders.

[UninstallDelete]
Type: files; Name: "{app}*"
Type: filesandordirs; Name: "{app}datadata1"
Type: filesandordirs; Name: "{app}datadata2"
Type: filesandordirs; Name: "{app}anotherfolder"

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...