Inno Setup仅卸载一些组件

时间:2016-05-29 07:32:52

标签: inno-setup uninstall pascalscript

我有一个常见的应用程序 - 比如媒体播放器 - 用于安装在同一文件夹中的每个不同的零售产品,即

  

C:\ program files \ myapp

和不同类似内容的电影都安装在同一个文件夹中

  

C:\ program files \ myapp \ movies

对于每个单独的安装(单独的零售产品),我只是创建一个快捷方式来打开具有mediaplayer -f movie1.mp4等特定内容的应用程序,但它可以打开来自同一环境的所有其他内容。

在我的情况下,问题是卸载。 Inno Setup不支持卸载组件选择。

我的策略(当时在我看来)是向用户提供一个自定义表单来选择要卸载的内容。例如。

[X] Main Application 
[X] Movie1 Full Title Description 
[X] Movie2 Full Title Description
[X] Movie3 Full Title Description

通过这种方式,通用卸载将适用于每个单独的零售安装。

问题

  1. 如何创建此类表单
  2. 如何扫描公共共享文件夹,例如此movies以查找所有已安装的内容,例如movie1.mp4movie2.mp4,.....
  3. 如何打开和阅读每部电影的标题,以读取一些数据,如完整标题,以便在卸载过程中显示它而不是文件名。
  4. 我曾经在DOS时代编写Pascal代码,但我现在是C ++ / MFC程序员。

    任何想法,建议,策略?

    最好的问候。

1 个答案:

答案 0 :(得分:2)

Inno Setup不支持部分卸载。

卸载完成后,将删除包含所有已安装组件(电影)的整个应用程序。

您可以做的是在InitializeUninstall中展示带有电影列表的自定义表单。如果用户选择仅卸载(某些)电影,而不是整个应用程序(观看者),则使用您自己的代码删除电影并中止卸载(通过从False返回InitializeUninstall)。如果用户选择卸载所有内容,则可以完成卸载。

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;

enter image description here