WiX Burn — определите, какие элементы уже установлены

У меня есть установка с записью, при которой пользователь может выбрать, какой из трех вариантов установки - каждый из них напрямую относится к одному из трех MsiPackages в цепочке, например:

<Chain>
  <MsiPackage SourceFile="..\ProductA\bin\Release\ProductA.msi"  InstallCondition="chkProductA" />
  <MsiPackage SourceFile="..\ProductB\bin\Release\ProductB.msi"  InstallCondition="chkProductA" />
  <MsiPackage SourceFile="..\ProductC\bin\Release\ProductC.msi"  InstallCondition="chkProductC" />
</Chain>

Все в порядке. Однако, когда я запускаю msi в следующий раз, я хочу только переустановить/обновить элементы, которые были выбраны изначально, т. е. если был выбран только продукт A, я не хочу устанавливать продукты B и C.

Как определить, что было выбрано изначально?


person Fetchez la vache    schedule 16.10.2012    source источник


Ответы (2)


ОК, разобрался, поэтому лучше опубликовать свое решение.

В итоге все сводится к двум частям...

а) установка ключа реестра в каждом из MSI-файлов Продукта, которые задаются при установке. Очевидно, что если этот MSI не был установлен изначально, записи в реестре не будет. т.е.

  <!-- registry entry to state that the item has been installed-->
  <Component Id="cmp_WriteToRegistry" Guid="[yourguid]">
    <RegistryKey Root="HKLM"
                 Key="Software\MyCompany]"
          Action="createAndRemoveOnUninstall">
      <RegistryValue Type="integer" Name="ProductA" Value="1" KeyPath="yes"/>
    </RegistryKey>
  </Component>

б) Проверка существования этого ключа реестра при записи при обновлении...

<!-- Determine what items are to be installed in the event of an install using the BA-->
<WixVariable Id="chkProductA" Value="![CDATA[chkProductA]]" />
<WixVariable Id="chkProductB" Value="![CDATA[chkProductB]]" />
<WixVariable Id="chkProductC" Value="![CDATA[chkProductC]]" />

<!-- Determine what items are installed in the event of an upgrade-->
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\MyCompany" Value="ProductAInstalled" Variable="ProductAInstalled" Result="exists" />
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\MyCompany" Value="ProductBInstalled" Variable="ProductBInstalled" Result="exists" />
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\MyCompany" Value="ProductCInstalled" Variable="ProductCInstalled" Result="exists" />

<Chain>
  <MsiPackage SourceFile="..\SetupProductA\bin\Release\SetupProductA.msi"
              InstallCondition="chkProductA OR ProductAInstalled" />
  <MsiPackage SourceFile="..\SetupProductB\bin\Release\SetupProductB.msi"
              InstallCondition="(chkProductB) OR (ProductBInstalled)" />
  <MsiPackage SourceFile="..\SetupProductC\bin\Release\SetupProductC.msi"
              InstallCondition="(chkProductC) OR (ProductCInstalled)" />
</Chain>

</Bundle>

Таким образом, в InstallCondition chkProductA оценивается как true, когда используется пользовательский интерфейс и установлен соответствующий флажок, а ProductAInstalled оценивается как true, когда соответствующий продукт уже установлен — заботясь об обновлении, которое в моем случае происходит без какого-либо взаимодействия с пользователем.

Легко, когда знаешь как. Я, конечно, не с того начал...

person Fetchez la vache    schedule 19.10.2012
comment
Старый этикет отвечать на свой собственный вопрос снова... Если у кого-то есть лучший ответ, я был бы очень рад услышать его, как будто это ответ, возможно, не ЛУЧШИЙ. Если через неделю или около того не будет лучших ответов, я установлю это как ответ. Я не гонюсь за очками, так что думаю, это правильно... - person Fetchez la vache; 19.10.2012
comment
Ваше решение, как я бы это сделал. Он похож на шаблон «Запомнить свойство»: robmensching.com/blog/posts/2010/5/2/ - person BryanJ; 19.10.2012
comment
Спасибо Брайан. Я все еще начинаю/изобретаю велосипед, так что это полезно знать. - person Fetchez la vache; 19.10.2012

Если вы создаете собственное управляемое приложение начальной загрузки, вы можете сделать это в обработчике событий DetectPackageComplete:

CustomBA_DetectPackageComplete(object sender, DetectPackageCompleteEventArgs e)
{
    if (e.PackageId == "SetupProductA" && e.State == PackageState.Present)
    {
        CustomBA.Engine.NumericVariables["chkProductA"] = 1;
    }
    etc...
}

То же самое можно сделать для обнаружения установленных функций с помощью DetectMsiFeature.

При этом я бы использовал этот метод только в том случае, если у вас уже есть собственный BA. Создание индивидуального бизнес-аналитика — это много работы.

person Dave Andersen    schedule 30.08.2013
comment
Вы также предлагаете выполнить поиск в реестре в пользовательском управляемом приложении Boostraper? - person dhiraj suvarna; 10.11.2015
comment
@phoenix, вам не нужно выполнять поиск в реестре, если вы включаете обновленную версию msi в свой пакет. Механизм записи обнаружит существующий msi на основе кода обновления соответствующего msi в вашем комплекте и запустит событие DetectPackageComplete. Джон Райт написал хороший пример обработки этого. - person Dave Andersen; 11.11.2015