How can I use bindpaths to create a WiX Patch?

2019-08-28 15:13发布

问题:

I'm using cmake/cpack to build my project with WiX.

cmake runs heat.exe (or something similar) which produces files.wxs that contains the files of my project in the following format:

We'll assume a single file named a.txt inside a folder named "bin". The project is built in NewFolder on the Desktop.

<DirectoryRef Id="CM_DP_bin">
    <Component Id="CM_CP_bin.a.txt" Guid="*">
        <File Id="CM_FP_bin.a.txt" Source="C:/Users/mindlessbot/Desktop/NewFolder/_CPack_Packages/WIX/packageName/bin/a.txt" KeyPath="yes"/>
    </Component>
</DirectoryRef>

After the MSI is created, the whole NewFolder is moved in a different directory (on our server). As a result, when I try to create a WiX Patch using the output .wixpdb, I get the following error:

error PYRO0103 : The system cannot find the file 'C:/Users/mindlessbot/Desktop/NewFolder/_CPack_Packages/WIX/packageName/bin/a.txt'

After some googling, I found out that the .wixpdb contains references to the files, which have changed location, so of course it can't find them. I found a thread where someone provided the commands to use bindpaths, however since I'm using cpack I can't directly call them.

So how should I got about doing this?

Some additional info:

My project contains multiple wxs files (not sure if it makes any difference)

The cpack command is:

path/to/cpack.exe -G WIX --config path/to/config.cmake

The patch command is run separately:

torch.exe -p -xi path/to/oldInstaller.wixpdb path/to/newInstaller.wixpdb -out path/to/patch.wixmst
candle.exe path/to/patch.wxs -out path/to/patch.wixobj
light.exe path/to/patch.wixobj -out path/to/patch/wixmsp
pyro.exe path/to/patch.wixmsp -out path/to/patch.msp -t PatchBaselineID path/to/patch/wixmst

回答1:

In the event that you would like to build your MSIs on one machine, but build the patch on another, I recommend using the .wixout approach rather than relying on the .wixpdb approach. A .wixout file may be generated by the same WiX Toolset CLI tool that is used to build the MSIs, light.exe. The .wixout

Full documentation on the WiX Toolset linker, light.exe, may be found here. The following is an example use of light.exe to build a .wixout file:

"C:\Program Files (x86)\WiX Toolset v3.11\bin\light.exe" "/path/to/Some.wixobj" "/path/to/Another.wixobj" "/path/to/AndYetAnother.wixlib" -bf -xo -out "/path/to/MyInstaller_v1.wixout"

So now let's breakdown what these command line parameters are for:

  • "/path/to/Some.wixobj" "/path/to/Another.wixobj" "/path/to/AndYetAnother.wixlib" - These are the compiled outputs of WiX source files, they may be either .wixobj files (generated through candle.exe) or .wixlib files (generated through lit.exe, a way of consolidating .wixobj files into one, shareable library).
  • -bf - This switch causes all of the files to be bound int the resulting .wixout file. This is what removes the need to have the exact folder structure on the target machine when building patches, because the files are carried with the .wixout file.
  • -xo - This switch tells the linker to output an XML representation of the MSI, instead of the actual MSI. This is required to use the -bf switch.
  • -out "/path/to/MyInstaller_v1.wixout" - This tells the linker where to output the .wixout file.

Once you have the capability of generating .wixout files, the torch.exe command can be modified to run based on .wixout files instead of .wixpdb files and their associated folder structures. The following is how I would modify your torch.exe command to use .wixout files as opposed to .wixpdb files:

torch.exe -p -xi "path/to/oldInstaller.wixout" "path/to/newInstaller.wixout" -out "path/to/patch.wixmst"

So, all in all I really like this approach, and generally I make my build process produce both an .msi and a .wixout file. This allows us to cache various builds/versions of our installer as .wixout files, and then the process of creating a patch between various versions of the .wixout files becomes relatively easy.



标签: cmake wix cpack