WiX 自定义操作在 MSI 中使用 [SourceDir] 和 Burn

Posted

技术标签:

【中文标题】WiX 自定义操作在 MSI 中使用 [SourceDir] 和 Burn【英文标题】:WiX Custom Action using [SourceDir] in MSI with Burn 【发布时间】:2014-07-08 11:46:27 【问题描述】:

我们的安装程序使用 CustomAction(在 InstallExecuteSequence 中调用)来选择性地从安装程序旁边的目录复制用户配置文件。这使用 [SourceDir] 来定位源目录。

我们目前有 32 位和 64 位版本,它们作为单独的 .MSI 文件分发。我正在尝试使用 Burn 构建一个包含这些 .MSI 文件的单个 .EXE。显然,当 Burn 安装 MSI 时,它的 [SourceDir] 位于其他位置(我看到 C:\ProgramData\Package Cache\... 路径),因此此自定义操作不起作用。

我找到了 WixBundleOriginalSource 变量,但我的问题是我希望 MSI 文件在与 Burn 打包时单独工作。我认为我需要有条件地将变量设置为 WixBundleOriginalSource(如果已定义(用户使用 Burn .exe 安装))或 SourceDir(如果未定义 WixBundleOriginalSource(用户直接安装 .MSI)),然后将此变量传递给我的自定义操作。 (我知道 WixOriginalSource 是安装程序的完整路径,而不是它所在的目录 - 我可以在我的自定义操作中处理它。)

这可能吗?如果是这样,请你帮我语法。

更新:

我可以在我的自定义操作中处理条件部分,并调用它两次:一次使用[SourceDir](直接使用 MSI 时有效),就像我现在所做的那样:

在我的产品中

    <CustomAction Id='CopyConfigFiles'
                  FileKey="MyInstallationUtility"
                  ExeCommand="COPYFILES [SourceDir]"
                  Execute="deferred"
                  Impersonate="no"
                  Return="ignore" />

... 和一次WixBundleOriginalSource。但是,我找不到让WixBundleOriginalSource 给我自定义操作的方法。使用:

                  ExeCommand="COPYFILES [WixBundleOriginalSource]"

... 不起作用。使用:

在我的刻录包中

    <WixVariable Id="ConfigFileLocation" Value="[WixBundleOriginalSource]" />

在我的产品中

                  ExeCommand="COPYFILES [ConfigFileLocation]"

... 也不起作用。两者都给我一个空字符串作为参数。

【问题讨论】:

这个问题的答案似乎可以回答我的最后一个问题:***.com/questions/17729878/… 【参考方案1】:

解决方法是在MSI脚本中定义一个可以被burn覆盖的Property,如果burn没有设置,则让MSI脚本设置为[SourceDir]。

在 MSI 脚本中,我们定义了属性(将其初始化为“未设置”,我们稍后会对其进行测试)和自定义操作以将其设置为 [SourceDir]:

    <Property Id='CONFIGFILELOCATION' Value='unset' />
    <CustomAction Id='MsiConfigLoc' Property='CONFIGFILELOCATION' Value='[SourceDir]' Execute='immediate' />

需要安装程序位置的自定义操作已更新为使用此新属性:

<CustomAction Id='CopyConfigFiles'
              FileKey="MyInstallationUtility"
              ExeCommand="COPYFILES [CONFIGFILELOCATION]"
              Execute="deferred"
              Impersonate="no"
              Return="ignore" />

然后将 InstallExecuteSequence 扩展为有条件地调用新的自定义操作(在 CopyConfigFiles 之前) - 仅当刻录 EXE 未设置 CONFIGFILELOCATION 时:

        <Custom Action='MsiConfigLoc' Before='CopyConfigFiles'>CONFIGFILELOCATION="unset"</Custom>
        <Custom Action='CopyConfigFiles' Before='InstallFinalize'/>

最后,在 Burn Bundle 中,我们将 CONFIGFILELOCATION 属性设置为 [WixBundleOriginalSource]:

        <MsiPackage SourceFile='ProductSetup.msi' DisplayInternalUI='yes'>
            <MsiProperty Name='CONFIGFILELOCATION' Value='[WixBundleOriginalSource]' />
        </MsiPackage>

从 WiX 3.9 开始,最好使用[WixBundleOriginalSourceFolder],因为它提供了安装程序可执行文件所在的目录。我在这里使用[WixBundleOriginalSource](安装程序可执行文件的完整路径)并处理剥离我的自定义安装代码中的文件名。

【讨论】:

以上是关于WiX 自定义操作在 MSI 中使用 [SourceDir] 和 Burn的主要内容,如果未能解决你的问题,请参考以下文章

如何在自定义操作 DLL (MSI/Wix) 中获取“INSTALLED”属性?

使用Wix在MSI中自定义操作出错时显示最终用户消息

无法将我的 WiX 自定义操作安排到 msi

Wix 自定义卸载操作 - 如何在 msi 删除文件之前运行

WiX:使用msiexec / i Setup.msi / qn时不运行自定义操作(没有UI的安静模式安装)

Wix 的 VC++ 自定义操作