I would like to keep my top level .wxs DRY while building 32 and 64 bit installers. I am using the -arch argument to candle.exe to control what default installer architectur
Rather than conditionally including the opening Directory
elements (which invalidates the XML), conditionally set preprocessor variables which are used as directory names, as @Daniel Pratt's comment refers to. Similarly, having a "yes/no" variable conditioned on platform makes it easy to set up 64 bit components, registry searches, etc.
(From this answer)
<?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)
is built-in, but its value is used to define custom variables $(var.ProductName)
, $(var.Win64)
and $(var.PlatformProgramFilesFolder)
.
You can either use preprocessor <?if
directives to test variables' values (as is done with $(var.Platform)
when defining the custom variables above) or have the preprocessor insert variables' values into XML attribute or element values. Couple of examples:
<Component Id="..." Win64="$(var.Win64)">
...
</Component>
This will produce warnings in the Visual Studio WiX editor about $(var.Win64)
not being one of the allowable attribute values (yes
/no
) but these can be safely ignored, because the preprocessor will have substituted an appropriate value by the time the compiler gets hold of it.
<Directory Id="$(var.PlatformProgramFilesFolder)">
...
</Directory>
In response to rharrison33's comment asking how to handle the requirement for different product codes (or pretty much anything) in the 32 and 64 bit installers (assuming you can't/don't want to auto-generate them):
candle <all other flags> -d ProductCode32=<guid1> -d ProductCode64=<guid2>
<?if ?>
branch: <?define ProductCode = "$(var.ProductCode32)" ?>
<?if ?>
branch: <?define ProductCode = "$(var.ProductCode64)" ?>
$(var.ProductCode)
in Product/@Id
.Made this CW because Daniel's link answers the question and has a lot more great info besides.
I had this problem with WiX 3.7. It was a tiny installer and I did not need the flexibility of variables so I hid the closing Directory tag from the parser by wrapping it in the same way as the opening tag:
<?if $(sys.BUILDARCH)=x64?>
<Directory Id="ProgramFiles64Folder">
<?else?>
<Directory Id="ProgramFilesFolder">
<?endif?>
...
<?if $(sys.BUILDARCH)=x64?></Directory><?else?></Directory><?endif?>
It's a hack, but it worked for my use case.