Inno Setup 仅卸载部分组件

2024-03-21

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

C:\程序文件\myapp

并且不同的内容(例如电影)都安装在同一个文件夹中

C:\程序文件\myapp\电影

对于每个单独的安装(单独的零售产品),我只是创建一个快捷方式来打开具有特定内容的应用程序,例如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.mp4, movie2.mp4, .....
  3. 如何打开并读取每部电影的标题以读取一些数据(例如完整标题)以在卸载过程中显示它而不是文件名。

我曾经在 DOS 时代编写 Pascal 代码,但现在我是一名 C++/MFC 程序员。

有什么想法、建议、策略吗?

此致。


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;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Inno Setup 仅卸载部分组件 的相关文章

随机推荐