Inno Setup Uninstall some components only

后端 未结 1 1318
难免孤独
难免孤独 2021-01-16 22:45

I have a common application -like a media player- for each different retail product that is installed in the same folder i.e.

C:\\program files\\myapp

1条回答
  •  太阳男子
    2021-01-16 23:21

    Inno Setup does not support partial uninstallations.

    Once the uninstallation completes, your whole application with all installed components (movies) will be deleted.

    What you can do is to present a custom form with movies list in the InitializeUninstall. If the user chooses to uninstall only (some) movies, but not whole application (the viewer), you delete the movies with your own code and abort the uninstallation (by returning False from the InitializeUninstall). If the user chooses to uninstall everything, you let the uninstallation complete.

    function InitializeUninstall(): Boolean;
    var
      Form: TSetupForm;
      OKButton, CancelButton: TNewButton;
      CheckListBox: TNewCheckListBox;
      I, Count, Deleted: Integer;
      FindRec: TFindRec;
      MoviePath: string;
      Movies: TArrayOfString;
    begin
      MoviePath := ExpandConstant('{app}\movies\');
      Count := 0;
      if FindFirst(MoviePath + '*', FindRec) then
      begin
        try
          repeat
            if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then
            begin
              Inc(Count);
              SetArrayLength(Movies, Count);
              Movies[Count - 1] := FindRec.Name;
            end;
          until not FindNext(FindRec);
        finally
          FindClose(FindRec);
        end;
      end;
    
      if Count = 0 then
      begin
        Log('Found no movies proceeding with a complete uninstallation');
        Result := True;
      end
        else 
      begin
        Log(Format('Found %d movies', [Count]));
    
        Form := CreateCustomForm();
        try
          Form.ClientWidth := ScaleX(350);
          Form.ClientHeight := ScaleY(250);
          Form.Caption := 'Uninstall';
          Form.Position := poDesktopCenter;
    
          CheckListBox := TNewCheckListBox.Create(Form);
          CheckListBox.Parent := Form;
          CheckListBox.Left := ScaleX(10);
          CheckListBox.Width := Form.ClientWidth - 2*CheckListBox.Left;
          CheckListBox.Top := ScaleY(10);
          CheckListBox.Height :=
              Form.ClientHeight - ScaleY(23 + 10 + 10 + CheckListBox.Top);
    
          CheckListBox.AddCheckBox(
            'Uninstall viewer and all movies', '', 0, True, True, True, True, nil);
          for I := 0 to Count - 1 do
          begin
            CheckListBox.AddCheckBox(Movies[I], '', 1, True, True, False, True, nil);
          end;
    
          OKButton := TNewButton.Create(Form);
          OKButton.Parent := Form;
          OKButton.Width := ScaleX(75);
          OKButton.Height := ScaleY(23);
          OKButton.Left := Form.ClientWidth - ScaleX(75 + 6 + 75 + 10);
          OKButton.Top := Form.ClientHeight - ScaleY(23 + 10);
          OKButton.Caption := 'OK';
          OKButton.ModalResult := mrOk;
          OKButton.Default := True;
    
          CancelButton := TNewButton.Create(Form);
          CancelButton.Parent := Form;
          CancelButton.Width := OKButton.Width;
          CancelButton.Height := OKButton.Height;
          CancelButton.Left := OKButton.Left + OKButton.Width + ScaleX(6);
          CancelButton.Top := OKButton.Top;
          CancelButton.Caption := 'Cancel';
          CancelButton.ModalResult := mrCancel;
          CancelButton.Cancel := True;
    
          Form.ActiveControl := CheckListBox;
    
          if Form.ShowModal() <> mrOk then
          begin
            Log('User cancelled the uninstallation');
            Result := False;
          end
            else
          begin
            if CheckListBox.State[0] = cbChecked then 
            begin
              Log('User selected complete uninstallation');
              Result := True; 
            end
              else
            begin
              for I := 0 to Count - 1 do
              begin
                if CheckListBox.Checked[I + 1] then
                begin
                  if DeleteFile(MoviePath + Movies[I]) then
                  begin
                    Inc(Deleted);
                    Log(Format('Deleted movie %s', [Movies[I]]));
                  end
                    else
                  begin
                    MsgBox(Format('Error deleting %s', [Movies[I]]), mbError, MB_OK);
                  end;
                end;
              end;
    
              MsgBox(Format('Deleted %d movies', [Deleted]), mbInformation, MB_OK);
              Result := False; 
            end;
          end;
        finally
          Form.Free();
        end;
      end;
    end;
    

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