我们实际上有一个设置,在安装过程中有很多组件选择,我们希望在客户重新安装我们的软件时禁用已安装的组件(或使其灰色/固定)。
例如,在第一次安装时,我们有3个这样的组件:
Component
* International
* French
* German
首次安装时,可以选择所有组件。
认识到选择“德语”包,当用户重新安装产品(使用相同的安装程序)以获得新的语言包时,我们希望有类似的东西:
Component
* International
* French
* German (already installed)
无法选择“德语”......
Inno Setup有没有办法做到这一点?
我找到了InnoSetup: Disable components page on upgrade,但该示例禁用了整个组件页面,我想保留它。
编辑:
这适用于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.
显然,在Software\Microsoft\Windows\CurrentVersion\Uninstall\AppId_is1\Inno Setup: Selected Components
上每次安装后都会创建inno-setup,这就是为什么它只适用于第二次安装,但是不记得第一次安装时会选择该组件。
答案 0 :(得分:1)
您可以从注册表值
中提取已安装组件的列表Software\Microsoft\Windows\CurrentVersion\Uninstall\AppId_is1\Inno Setup: Selected Components
问题是该列表使用组件名称,并且无法将名称映射到复选框,因为只有编程方式公开了描述(另请参阅How to allow to only install specific components in InnoSetup?)。
幸运的是,Inno Setup本身将检查以前安装的组件。因此,最简单的解决方案是禁用所有初始检查的组件。如果在默认情况下选中的升级中添加新组件,这将会破坏。
另一种方法是使用WizardSelectedComponents
support function,它可以返回所选组件名称和描述的列表。因此,它可用于将描述映射到名称和返回。但仅适用于选定的组件。虽然这应该足以满足您的特定目的。请参阅我的代码中的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;