📜 ⬆️ ⬇️

Creating a patch on Wix with PatchWiz


Good day to all! I would like to share with all my experience of creating a system for generating patches (may the reader forgive me for using this word). There was a lot written about wix here and I assume that the reader is a little familiar with it, but somehow they have bypassed the problem of creating patches. In our company, they are widely used, mainly because of its size, and also because of the possibility of rollback.

To begin, I will describe the task that I encountered, then I will describe the basic information for creating patches. I will also do the 2nd part with a specific example, utilities to simplify this process and source codes.

Task:


1. There is a highly specialized desktop product that is installed in many subjects of the Russian Federation to many branches of the authority related to forestry. Let's name this conditional product for convenience, let's say Ash.
2. For each subject, their own installation version is assembled, which do not differ in binary, but content differs in files that do not change (maps, report templates, basic database, etc.).
3. In the “hot” season, updates are released every 1-2 weeks (everyone suddenly needs something and often something new). The product version changes (either major , minor or build )
4. At any time, any client can ask for both the update and the full version. It is necessary to get out of the situation with minimal costs.
5. ClickOnce is not suitable, as some government agencies, oddly enough, do not have direct access to the Internet, or it is very bad.
6. Do everything on Wix , since it is free.

Under these conditions (point 4!), In order to save traffic and not send 100 MB of full version each time it’s better to make patches.
')
There are a couple of whims of developers:
1. And you also want freedom in passing patches, that is, you can, for example, be updated after 1 or 2 updates.
2. On the scheme of possible updates, this whim looks like this:


That is, all variants of the sequence are allowed:
• Consistently get all the patches, then get the full msi (solid line).
• Skip 2 patches, put the 3rd, and then I understand msi (dotted).
• Put 1 patch, 1 skip, next put and get the full version of msi.
• etc.
Let's start from the beginning.

Understand the versions and patches


As is known, the version in Wix consists (= takes into account) of 3 numbers: xyz, x - Major version , y - Minor version , z - Build number . The principle of changing these values, in my opinion, is determined by the company, and there is no explicit rule, only recommendations .
At the same time, there are 3 types of updates:

"Base" for updates in Wix

The implementation of the listed update options in Wix is ​​based on 2 variables:
1. The UpgradeCode attribute of the Product element.
2. The ProductCode attribute of the Product element.
About Package.Id we do not speak, as it changes almost always. Details on when to change UpgradeCode and ProductCode are written here and here .
In short it is like this:

Example

Suppose there is an already installed application version 1.0, we are creating the next version of the installation. We can change the UpgradeCode and ProductCode in it to a new value relative to the previous version.
Let's see what happens if we change \ leave the old values ​​of these attributes. Our success in trying to (1) create a package and (2) install it is reflected in the table below:

We get: * - minor update , ** - major update , *** - small update

The general approach of creating a patch

The procedure of creating a patch in general looks very simple: there is one or several “basic” assemblies and one “final” one. The patch generation utility creates a package that can update the product from versions that are contained in the “base” builds to the version that is contained in the “final” one.

As is known, Wix supports 2 technologies for creating patches: using PatchWiz.dll and Wix itself. I will not go deep into the analysis of all the advantages and disadvantages of these options. This is not the purpose of the article. Let me just say that as a result of our experiments, we stopped at the first option (because only on it could we get a result that satisfies us).

Creating a patch on Wix using PatchWiz.dll


To create a patch using PatchWiz (we will use the utility msimsp.exe ) you need at least 2 installation packages (or more precisely 2 msi files) and a patch handle (usually the file is called Patch.wxs ). I will not describe in detail all the possibilities that they have provided, otherwise the article will turn out too big, but I will touch on the main points. (Details can be found here )

1. First, create Patch.wxs , and in it the element PatchCreation .

<PatchCreation Id="{42D7EE3B-A712-4AD4-9B23-A8710FC486FA}" Codepage="1251" CleanWorkingFolder="yes" OutputPath="patch.pcp" WholeFilesOnly="yes"> 

Here:
Id - a unique patch Id, always new.
Codepage is the code page for the intermediate (for us) file with the PCP extension.
CleanWorkingFolder - clear the temporary folder after creating the patch.
OutputPath - the path and name of the intermediate file.
WholeFilesOnly - in the patch we will include the changed files as a whole, and not just the changed blocks in them.

Inside the PatchCreation elements are recorded with information about the patch, here, I think, everything is clear (PatchMetadata is not a mandatory element).

 <PatchInformation Description=" " Comments="   1.1" Manufacturer="  "/> <PatchMetadata AllowRemoval="yes" Description=" " ManufacturerName="  " TargetProductName="" MoreInfoURL="http://./" Classification="Update" DisplayName="    1.1"/> 

And, perhaps, the main thing: we indicate the paths where the base assemblies and the final ones lie.

 <Family DiskId="2" Name="Yasen" SequenceStart="5000"> <UpgradeImage SourceFile="C:\Work\Yasen\v1.1\Setup.msi" Id="NewPackage"> <TargetImage SourceFile="C:\Work\Yasen\v1.0.8\Setup.msi" Order="2" Id="BasePackage1"/> <TargetImage SourceFile="C:\Work\Yasen\v1.0\Setup.msi" Order="3" Id="BasePackage2"/> </UpgradeImage> </Family> 

Here:
DiskId is the number of the new entry in the Media table, it should not be the same as the Media Id of the basic installer.
Name - the name of the update line. I did not try to update one product with updates with different Family Names.
SequenceStart - the number to be written in the InstallExecuteSequence table, must not be the same as existing records. In most of the examples I’ve seen, it costs 5000. This value does not conflict with the standard Wix values; in our package this value is also not used. (Details about this are in the articles about wix listed above)

Element UpgradeImage - describes the final assembly.
SoureFile - the path to the final assembly (in fact, not entirely on it, but on its "unpacked" version, this is written below)
Id - build identifier.

The TargetImage element describes those assemblies that can be updated by the current update.
SourceFile - the path to the base assembly.
Order - the order of the basic assemblies (I still do not understand why this is necessary).
Id - ID of the base assemblies.

And at the end of the PatchCreation, the PatchSequence element is inserted.

 <PatchSequence PatchFamily= "Yasen" Sequence="1.1.0.0" Supersede="yes" ProductCode="{7381ABA7-774B-4D44-BD7B-0A90BBCF2B0A}" /> 

Here:
PatchFamily - indicates to which line this patch belongs (somewhere we have already seen this?)
Sequence - indicates the version of the patch to distinguish in which order the patches were released. Specified in xxxx format
Supersede - indicates whether this patch can cancel all previous patches (cumulative patch?)
ProductCode - product code (apparently, not to be mistaken).

Assembly and installation


After the installation and the patch descriptor are ready, do the following:

1. Perform an administrative installation of all installations in separate folders, for example, like this:

 msiexec.exe /a 1.0\product.msi /qb TARGETDIR=C:\sample\1.0\admin msiexec.exe /a 1.1\product.msi /qb TARGETDIR=C:\sample\1.1\admin 

Please note that the path to installations in PatchCreation should point to these "unpacked" versions, for example, C: \ sample \ 1.0 \ admin \ product.msi

2. Compile the Wix files:
 candle.exe patch.wxs light.exe patch.wixobj -out patch.pcp 

3. Use the utility from PatchWiz :
 msimsp.exe -s patch.pcp -p patch.msp -l patch.log 

And we finally got what we wanted!

Total


We got the desired patch, but to solve the problem we need something more:


Accordingly, to address these inconveniences, I will write the second part and describe everything I promised at the beginning of the post.

References:
Wix tutorial (very good manual)
Wix - Creating patches
MSDN - Patching and Upgrades

Source: https://habr.com/ru/post/190546/


All Articles