Patch Families in WiX and Windows Installer

Patch Families in WiX and Windows Installer

  • Comments 5

Patch families were introduced in Windows Installer 3.0 as a means to sequence patches even if applied in any order, and to supersede previous patches. Supersedence allows for easier delta patching and allows more patches to be installed than the 127 limit.

When we started developing the new patch build support in Windows Installer XML (WiX) 3.0, we overloaded the concept of patch families to filter resources in a transform. By adding references to symbols to a PatchFamily element, that symbol and all other elements in the same fragment are left in the authoring transform. Every other difference between the target and upgrade products are removed. Effectively, this is like removing everything you didn't specify in the target and upgrade products, then building a transform between the two databases. Using tools like PatchWiz.dll, this was the only way to create a patch that included only a subset of changes.

Patch families at build time are used as a logical grouping of resources. But once the patch is built, resources really belong to all patch families. Remember that a patch package is really just a collection of transforms and zero or more cabinets; and that when applying a patch to a product, the first applicable authoring transform is applied to a product individually. Even if a patch applies to multiple products, each product is transformed separately. If taking advantage of the multi-product transaction feature shipping in Windows Installer 4.5, installation scripts are still generated per-product and merely executed sequentially in a single transaction.

So because patches are applied to a product individually and sequenced and superseded all in relation to that product, all patch families affect sequencing and supersedence with other patches applied to that product. Patch families are attributes of a patch, and there is no relationship in a patch package to resource changes in a transform.

Consider product MSIa which contains a.dll, and product MSIb which contains b.dll. A patch is built that applies to both products. In the patch source file, file resource a.dll is added to patch family PFa, and file resource b.dll is added to patch family PFb. The resulting .msp patch package contains both patch families PFa and PFb. Now when that patch is applied to product MSIa, both patch families PFa and PFb are considered when sequencing and superseding. In a debug Windows Installer log, you can see this at the top of the log before the requested ACTION is even started.

To put it another way, the resource changes are defined in a transform to a product while the patch families are defined in a patch. Patches are sequenced with other patches for an individual product, and once the patch applicability and order are determined then the applicable transforms within those remaining patches are applied to the product in the order of the patches.

Why is this important?

For one reason, if you build a multi-product patch like in the example above but later build a single-product patch with just one of the patch families, the newer single-product patch will not supersede the older multi-product patch. You have to supersede all patch families in previously sequenced patches to supersede that patch. Now, effectively you've updated the same resources in the target product but both patches are still registered. This will likely only be a problem if you install so many patches you exceed the 127 patch limit or are trying to apply delta patches to the same file resources.

Another reason is that if you moved a.dll to patch family PFb and installed the same multi-product patch to product MSIa, a previous patch containing only patch family PFa will not sequence correctly with the new patch containing only patch family PFb. At least one patch family must be common between patches for them to sequence correctly in relationship to each other. Moving a resource from one patch family to another effectively shrinks one patch family, and patch families should only ever grow; though, defining new, unique patch families is recommended for flexibility.

So remember that patch family definitions at build time affect what changes are kept in a transform, while all patch families in a patch at install time affect sequencing and supersedence with other patches applied to a single product.

Leave a Comment
  • Please add 1 and 6 and type the answer here:
  • Post
  • PingBack from

  • I am trying to write a multi-target patch for multiple MSIs. The MSIs have the same upgrade code but different product codes. We have a separate MSIs for our engine, our client and a number for addins.

    I am using WiX 2 (build 5805) to create the pcp file and MsiMsp.exe (3.1.4000.1830) to create the msp file and trying to install onto Windows XP, SP2 with Windows install 3.01.4000.1823

    The transform storage looks correct (orca can apply the patch to each product msi) but when you run the msp it only applies the patch to one MSI.

    I was expecting it to run as if I had put multiple patches on the command line and patch each product referenced in the msp.

    Do you know if that is wrong expectation or if I am doing something wrong? :-(

    Thanks in advance,


  • You can ignore the previous post. As it suddenly started working. :-)

    Well, I think what happened was that the patch wanted to do a reboot which interrupted the processing. So I thought that it didn't want to apply the rest of the patches. When I ran the patch again it managed to do more products.


  • ttanner, that's one of the biggest reasons we use chainers a lot - to ignore the 3010 (ERROR_SUCCESS_REBOOT_REQUIRED) and do it at the end. Depending on your scenarios and likelihood of multiple target products installed on the same machine, you might consider doing the same.

  • Hi Heath.. I have create a patch which is also uninstallable patch after applying the patch I can find my original files(dlls) are cached to baseline cache. But upon uninstall of my patch not all patched dlls are reverted back to the original version. So I wonder what could be reasons that some dlls are not reverted back upon uninstall of my patch. Note: dlls are in question not marked as shared components in components table attribute field for those component I find value as 0 which is as designed

Page 1 of 1 (5 items)