升级时禁用已安装的 Inno Setup 组件

问题描述 投票:0回答:1

我们实际上有一个设置,在安装过程中有很多组件选择,我们希望在客户重新安装我们的软件时禁用已安装的组件(或使其变为灰色/固定)。

例如,在第一次安装期间,我们有 3 个组件,如下所示:

Component
* International
* French
* German

首次安装时,可以选择所有组件。

认识到选择“德语”包,当用户重新安装产品(使用相同的安装程序)以获得新的语言包时,我们希望有类似的东西:

Component
* International
* French
* German (already installed)

其中“德语”不能选择...

有没有办法用 Inno Setup 来做到这一点?

我找到了InnoSetup:升级时禁用组件页面,但该示例禁用了整个组件页面,我想保留它。

编辑

这适用于 2 个安装。但是,如果我进行第三次安装(用于安装最后一个组件),则安装程序将采用第二次安装的组件,而不是第一个安装的组件。

我认为这是因为安装程序覆盖了第一次安装的注册表项,因此看不到早期安装的组件...

这是首次安装时的日志和注册表项(选择英文):

2016-03-22 13:57:56.913   New install de Bim

这是第二次安装时的日志和注册表项(英语为灰色且无法选择,法语已选择):

Created temporary directory: C:\Users\mea\AppData\Local\Temp\is-QV8N6.tmp
2016-03-22 14:00:54.354   Upgrading, previously installed components are [languagepacks,languagepacks\english,canecorevit,canecorevit\2016]
2016-03-22 14:00:54.354   Found installed component [languagepacks]
2016-03-22 14:00:54.354   Disabling installed component [languagepacks] as [Content] at 0
2016-03-22 14:00:54.355   Found installed component [languagepacks\english]
2016-03-22 14:00:54.355   Disabling installed component [languagepacks\english] as [Pack International] at 1
2016-03-22 14:00:54.355   Found installed component [canecorevit]
2016-03-22 14:00:54.356   Found installed component [canecorevit\2016]
2016-03-22 14:00:54.356   Disabling installed component [canecorevit\2016] as [REVIT 2016] at 5
2016-03-22 14:02:48.691   Message box (Yes/No):
                          L'assistant d'installation a détecté que les composants suivants sont déjà installés sur votre système :

                          Pack International

                          Désélectionner ces composants ne les désinstallera pas pour autant.

                          Voulez-vous continuer malgré tout ?
2016-03-22 14:02:49.808   User chose Yes.
2016-03-22 14:02:56.000   Starting the installation process.

这是第三次安装的日志和注册表项

Created temporary directory: C:\Users\mea\AppData\Local\Temp\is-J7G5A.tmp
2016-03-22 14:07:41.582   Upgrading, previously installed components are [languagepacks,languagepacks\french,canecorevit,canecorevit\2016]
2016-03-22 14:07:41.583   Found installed component [languagepacks]
2016-03-22 14:07:41.583   Disabling installed component [languagepacks] as [Content] at 0
2016-03-22 14:07:41.583   Found installed component [languagepacks\french]
2016-03-22 14:07:41.584   Disabling installed component [languagepacks\french] as [Pack France] at 2
2016-03-22 14:07:41.584   Found installed component [canecorevit]
2016-03-22 14:07:41.584   Found installed component [canecorevit\2016]
2016-03-22 14:07:41.585   Disabling installed component [canecorevit\2016] as [REVIT 2016] at 5
2016-03-22 14:08:14.122   Message box (Yes/No):
                          L'assistant d'installation a détecté que les composants suivants sont déjà installés sur votre système :

                          Pack France

                          Désélectionner ces composants ne les désinstallera pas pour autant.

                          Voulez-vous continuer malgré tout ?
2016-03-22 14:08:15.132   User chose Yes.

很明显,inno-setup 在每次安装后都会写入

Software\Microsoft\Windows\CurrentVersion\Uninstall\AppId_is1\Inno Setup: Selected Components
,这就是为什么它只适用于第二次安装,但不记得在第三次安装期间在第一次安装中选择了组件。

inno-setup pascalscript
1个回答
1
投票

您可以从注册表值中提取已安装组件的列表

Software\Microsoft\Windows\CurrentVersion\Uninstall\AppId_is1\Inno Setup: Selected Components

问题是列表使用组件名称,并且无法将名称映射到复选框,因为仅以编程方式公开描述(另请参阅如何允许在 Inno Setup 中仅安装特定组件?

幸运的是,之前安装的组件将由 Inno Setup 本身进行检查。因此,最简单的解决方案是禁用所有最初检查的组件。如果您在默认情况下选中的升级中添加新组件,则会破坏这一点。

另一种方法是使用

WizardSelectedComponents
支持功能,它可以返回所选组件名称和描述的列表。因此它可用于将描述映射到名称并映射回来。但仅适用于选定的组件。尽管这对于您的特定目的来说应该足够了。请参阅我的代码中的
SelectedComponentDescriptionToName

一个限制是描述必须是唯一的,否则映射失败。因此,您不能拥有不同父组件的多个“Deutsch”子组件(这将需要更复杂的代码,并且如果父组件具有

checkablealone
标志,则根本无法工作)

#define AppId "myapp"
#define InnoSetupReg \
  "Software\Microsoft\Windows\CurrentVersion\Uninstall\" + AppId + "_is1"
#define InnoSetupSelectedComponentsReg "Inno Setup: Selected Components"

[Setup]
AppId={#AppId}
...

[Code]

function ExtractToken(var S: string): string;
var
  P: Integer;
begin
  P := Pos(',', S);
  if P > 0 then
  begin
    Result := Copy(S, 1, P - 1);
    Delete(S, 1, P);
  end
    else
  begin
    Result := S;
    S := '';
  end;
end;

function SelectedComponentDescriptionToName(Description: string): string;
var
  Descriptions: string;
  Names: string;
begin
  Descriptions := WizardSelectedComponents(True);
  Names := WizardSelectedComponents(False);

  while Descriptions <> '' do
  begin
    Result := ExtractToken(Names);
    if RemoveQuotes(ExtractToken(Descriptions)) = Description then
    begin
      Exit;
    end;
  end;

  Result := '';
end;

procedure InitializeWizard();
var
  Upgrade: Boolean;
  SelectedComponents: string;
  Component: string;
  Name: string;
  I: Integer;
begin
  Upgrade :=
    RegQueryStringValue(HKCU, ExpandConstant('{#InnoSetupReg}'), 
      '{#InnoSetupSelectedComponentsReg}', SelectedComponents) or
    RegQueryStringValue(HKLM, ExpandConstant('{#InnoSetupReg}'),
      '{#InnoSetupSelectedComponentsReg}', SelectedComponents);

  if not Upgrade then
  begin
    Log('New install');
  end
    else
  begin
    Log(Format('Upgrading, previously installed components are [%s]', [
      SelectedComponents]));

    while SelectedComponents <> '' do
    begin
      Component := ExtractToken(SelectedComponents);

      Log(Format('Found installed component [%s]', [Component]));

      for I := 0 to WizardForm.ComponentsList.Items.Count - 1 do
      begin
        if WizardForm.ComponentsList.State[I] = cbChecked then
        begin
          Name :=
            SelectedComponentDescriptionToName(
              WizardForm.ComponentsList.ItemCaption[I]);

          if Name = Component then
          begin
            Log(Format('Disabling installed component [%s] as [%s] at %d', [
              Name, WizardForm.ComponentsList.ItemCaption[I], I]));
            WizardForm.ComponentsList.ItemEnabled[I] := False;
          end;
        end;
      end;
    end;
  end;
end;
© www.soinside.com 2019 - 2024. All rights reserved.