【问题标题】:WiX Burn - Determine what items are already installedWiX Burn - 确定已安装的项目
【发布时间】:2012-10-16 14:41:16
【问题描述】:

我有一个刻录安装,用户可以选择安装三个选项中的哪一个 - 每个选项都直接与链中的三个 MsiPackage 之一相关,例如:

<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 时,我只想重新安装/更新最初选择的项目 - 即如果只选择了 productA,我不想安装产品 B 和 C。

如何确定最初选择的是什么?

【问题讨论】:

    标签: wix installation wix3.6 bootstrapper burn


    【解决方案1】:

    好的, 已排序,所以我最好发布我的解决方案。

    最终归结为两部分......

    a) 在安装时设置的每个产品 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>
    

    b) 在升级时检查该注册表项是否存在...

    <!-- 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 中, 当使用 UI 并选中相应的复选框时,chkProductA 的计算结果为 true,并且 当相应的产品已经安装时,ProductAInstalled 评估为 true - 处理更新,在我的情况下,无需任何用户交互即可发生。

    当你知道怎么做时很容易。我当然不是一开始就...

    【讨论】:

    • 再次回答你自己的问题的旧礼仪......如果有人有更好的答案,我会很高兴听到它,好像上面是一个答案,它可能不是最好的.如果一周左右没有更好的答案,我会将其设置为答案。我不是在钓鱼,所以猜这是正确的做法......
    • 你的解决方案就是我会怎么做。类似于“记住属性模式”:robmensching.com/blog/posts/2010/5/2/…
    • 谢谢布莱恩。我仍处于初学者/重新发明轮子阶段,所以很高兴知道。
    【解决方案2】:

    如果您正在创建自己的托管引导程序应用程序,则可以在 DetectPackageComplete 事件处理程序中执行此操作:

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

    可以使用DetectMsiFeature 执行类似的操作来检测已安装的功能。

    话虽如此,如果您已经拥有自定义 BA,我只会使用此方法。构建自定义 BA 是一项大量工作。

    【讨论】:

    • 您是否也建议在自定义托管助推器应用程序中进行注册表搜索?
    • @phoenix,假设您在捆绑包中包含更新版本的 msi,则无需进行注册表搜索。刻录引擎将根据捆绑包中相关 msi 的升级代码检测现有的 msi,并触发“DetectPackageComplete”事件。 John Wright 写了 a nice example 来处理这个问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多