使用Wix从一个.wxs文件创建32位和64位安装程序

33

我想在构建32位和64位安装程序时保持顶级的.wxs文件DRY。我正在使用-arch参数来控制candle.exe正在构建的默认安装程序架构。

我目前遇到的问题是,32位和64位(ProgramFiles64Folder)架构之间的ProgramFilesFolder不同。这是我的第一次尝试解决:

<?if $(sys.BUILDARCH)=x64 ?>
<Directory Id='ProgramFiles64Folder' Name='PFiles'>
<?else ?>
<Directory Id='ProgramFilesFolder' Name='PFiles'>
<?endif ?>
    <Directory Id='the-rest' Name="Company Name">
...

我尝试过这个方法,但出现了错误。显然,在预处理器被评估之前,XML验证就已经开始了。当我手动更改为使用ProgramFiles64Folder时,我的构建可以正常工作。

我尝试了DirectoryRef路线,但没有成功。是否有任何建议可以让它在不需要在.wxs文件内进行sed替换的情况下正常工作?

注意:我在Wix 3.5和3.6中都尝试过这个方法。


6
我会使用这个答案中描述的技巧:https://dev59.com/UHRB5IYBdhLWcg3w6LV2#577793 - Daniel Pratt
2个回答

54

与其有条件地包含打开的Directory元素(这会使XML无效),不如有条件地设置预处理器变量用作目录名称,正如@Daniel Pratt的评论所指。同样,根据平台设置一个“是/否”变量可以轻松设置64位组件、注册表搜索等。

定义变量

(来自此答案

<?if $(var.Platform) = x64 ?>
  <?define ProductName = "Product Name (64 bit)" ?>
  <?define Win64 = "yes" ?>
  <?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?else ?>
  <?define ProductName = "Product Name" ?>
  <?define Win64 = "no" ?>
  <?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
<?endif ?>
$(var.Platform)是内置的,但它的值用于定义自定义变量$(var.ProductName)$(var.Win64)$(var.PlatformProgramFilesFolder)

使用变量

您可以使用预处理器<?if指令测试变量的值(如上面定义自定义变量时使用$(var.Platform)),或将预处理器插入变量的值到XML属性或元素值中。以下是一些例子:

32/64位组件

<Component Id="..." Win64="$(var.Win64)">
   ...
</Component>

这将在Visual Studio WiX编辑器中产生警告,提示$(var.Win64)不是允许的属性值之一(yes/no),但这些警告可以安全地忽略,因为预处理器在编译器获取它之前将替换为适当的值。

32/64位Program Files目录

<Directory Id="$(var.PlatformProgramFilesFolder)">
  ...
</Directory>

更新以处理单独的32/64位产品代码

回复rharrison33的评论,问如何处理在32位和64位安装程序中需要不同产品代码(或几乎任何内容)的要求(假设您不能/不想自动生成它们):

  • 在命令行或使用响应文件时,将单独的产品代码作为预处理器变量传递给candle:
candle <所有其他标志> -d ProductCode32=<guid1> -d ProductCode64=<guid2>
  • 将产品代码添加为与架构相关的预处理器变量之一,并将其设置为适当的输入变量:
    • 在32位<?if ?>分支中:<?define ProductCode = "$(var.ProductCode32)" ?>
    • 在64位<?if ?>分支中:<?define ProductCode = "$(var.ProductCode64)" ?>
  • Product/@Id中引用$(var.ProductCode)

之所以将其设置为社区wiki是因为Daniel的链接回答了这个问题,而且除此之外还有更多很好的信息。


2
这基本上就是我所做的。现在我已经包含了一个config.wxi文件,其中定义了正确的平台程序文件夹。 - KevM
1
@rharrison33 如果您无法自动生成产品代码,请查看我的编辑。 - anton.burger
@shambulator 运行得非常好!谢谢! - rharrison33
1
“<Component Id="..." Win64="$(var.Win64)">”与仅使用“<Component Id="...">”有何不同?默认值不是由平台自动确定的吗? - Joey Adams
我需要设置不同的UpgradeCodes吗? - pinki
显示剩余4条评论

8

我在使用WiX 3.7时遇到了问题。因为我的安装程序很小,不需要使用变量,所以我通过与开放标签相同的方式来包装关闭Directory标签,从而将其隐藏在解析器中:

<?if $(sys.BUILDARCH)=x64?>
    <Directory Id="ProgramFiles64Folder">
<?else?>
    <Directory Id="ProgramFilesFolder">
<?endif?>

...

<?if $(sys.BUILDARCH)=x64?></Directory><?else?></Directory><?endif?>

这是一个hack,但它适用于我的使用情况。


2
谢谢分享,这有助于理解问题的根本原因。 :-) - CodeFox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接