WiX patching

По-русски

To create Windows Installer packages, WiX is used in a project I work on. And one day I needed to create a patch for an existing install package.

I started searching how it can be done. The first thing that Google found was this instruction. It suited my needs, more or less. Yet I didn’t manage to create the patch following this instruction. I overcame several obstacles, and then I faced another problem on the last step of the process: the tools didn’t see any modifications between the two different installations. Later I found out why the tools see no modifications. It proved that our packages didn’t store the sizes of files.

The instruction I talked above was written for version 2.0 of WiX. However version 3.0 is already used. It took me some time until I found the updated instructions on the WiX site. There are two of them:

There was an issue with both ways: either instruction assumed there’s original .wsx file of the install package. I didn’t have one. After trying various approaches, including install package decompilation, I still didn’t manage to create patch. I even downloaded a fresh WiX build, but it didn’t help either.

Then I decided to start it all over and to begin with checking the instruction itself. I created a small package and an updated package. And I managed to create the patch between these two.

When I searched for solutions, I came across a post “Patching something you didn’t build with WiX using WiX”. It describes the procedure of creating patch from .msi files. That’s what I needed. Yet there were no details. The post stated that the command lines are the same as in “Building a Patch using the new Patch Building System – Part 3” post. But the instructions there simply repeat what’s written in the WiX documentation.

I used administrative install and option -ax instead of -xi, as it was described. And torch.exe failed with the same error as in the second comment: torch.exe : error TRCH0001 : The Windows Installer service failed to start. Contact your support personnel.

After I re-read all the comments carefully, I found a hint in the seventh comment: option -xo. This hint helped to create the patch.

Detailed Instruction

This instruction assumes you work in C:\patch.

  1. Perform administrative install:

    msiexec /a install.msi /qb TARGET=C:\patch\rtm
  2. Copy the image:

    xcopy /i rtm upp
  3. Using Orca, change the package code in the updated install image:

    1. On the File menu, click Open.
    2. In the Open dialog, type C:\patch\upp\install.msi and click Open.
    3. On the View menu, click Summary Information.
    4. Find Package code field and click New GUID to the right of it. The package code will be updated. Click OK.
    5. On the File menu, click Save to save the package.

    The Orca editor is part of Windows SDK.

  4. Update the files under C:\patch\upp with the new versions.
  5. Evaluate the differences between the two packages:

    torch -p -ax C:\patch\temp -xo rtm\install.msi upp\install.msi -out patch\diff.wixmst
  6. Create patch description file patch.wsx. You can take it from Create your patch authoring in the sample root section of the WiX instructions.

    I created my own based on it.

    <?xml version="1.0" encoding="UTF-8"?>
    <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
        <Patch 
            AllowRemoval="yes"
            Manufacturer="Organization" 
            DisplayName="Patch name"
            Description="Patch description"
            Comments="Patch comment"
            Classification="Update"
            Codepage="1251"
            >
     
            <Media Id="5000" Cabinet="ProductP.cab">
                <PatchBaseline Id="RTM"/>
            </Media>
        </Patch>
     </Wix>
    

    The Id in the Media element must be greater than the number of files in the original image; it should also take files from previous patches into account. If you’re authoring a second patch and the previous patch used 5000 as Id and updated 11 files, then this number must be greater than 5011.

  7. Create the patch itself:

    candle patch.wsx
    light patch.wixobj -out patch\patch.wixmsp
    pyro patch\patch.wixmsp -out patch\patch.msp -t RTM patch\diff.wixmst
  8. The patch is ready. It’s time to verify it works as expected. To do it, install the original install package, then install the patch and check the files were really updated.

In my case patch installation wasn’t smooth: the patch needed to update files which were not KeyPath of a Component. I guess no one thought about it when the installation package was created. In order to install the update correctly, property REINSTALLMODE must contain a mode. It was issued as warning by pyro.exe. So one needs to use the following command line:

msiexec /p patch.msp /qb REINSTALL=ALL REINSTALLMODE=omusa

Without /qb option, the full UI with Modify, Repair, Remove buttons is displayed, which is not quite great. I tried to click Modify and then click Next; patch installed successfully in this case. I didn’t try to click other buttons.

12 Responses to “WiX patching”

  1. Sunil Says:

    Can you please explain the 4th point (Update the files under C:\patch\upp with the new versions.)

    How to update and how files came her?

    • alexyv Says:

      According to step 2, the upp is the same as rtm.
      So in step 4, I took the updated files from a newer build and put them to the corresponding places. In my case, there were only several files that needed updating. (Other files, however, were binary different after a re-build.)

      • Sunil Says:

        Hi alexyv. I was successful in creating the patch and it worked perfect with test files. But now using the same steps with original files, I am puzzled.

        I have lots of sql files too which my installer executes on the sql server. But I am not able to create any custom action in this patch which will execute my sql files present in patch.

        Can you please post some sample code for same?

  2. preethi selvaraju Says:

    Hi,

    I created patch file using the following ways.

    1) Using pyro and torch , I have created patch(.msp) and its
    working fine. But when I made any changes in merge modules that is not
    reflected after patch is installed.

    2) Using .pcp, I have created patch(.msp) file. When I installing
    the patch, it is showing “Repair”. But no changes are reflected.
    I used msiexec /p patch.msp /qb REINSTALL=ALL REINSTALLMODE=omusa also.
    So I used Orca to view the changes. First , opened the targeted msi,
    then Transform->View Patch. In that, I can able to see the changed
    files. But after installing the patch, that wont be reflected.

    I cannot able to find the solution for this problem.

    Please advice.

    • alexyv Says:

      Hi Preethi,
      Try to run your patch with verbose logging, I think it could be because of conditions set in the merge modules.
      Does REINSTALL=ALL REINSTALLMODE=omusa not help with the 1st approach?

      (I believe you creating patch by comparing the original MSI and the new one. Because what I described in the post may not work with merge modules.)

  3. Minh Says:

    Hi Alexey,

    Thank for your instruction. This post help me a lot. However, in case my software have 2 version 1.1.2 and 1.1.3. Version 1.1.3 add more 3 files, I can create the patch file. But when I install patch file, I encountered error: “The file ‘My file 01’ cannot be installed because the file cannot be found in cabinet file ‘ProductP.cab’. This could indicate a new network error, an error reading from the CD-ROM, or a problem with this package”. How can I overcome this issue?

    • Alexey Ivanov Says:

      Hi Minh,

      I’m really glad this instruction helped you.
      Sorry but I don’t know the answer to your question. It looks Windows Installer engine knows it should install new files but it doesn’t know where to get them from. Do both MSI packages have cabinets attached to them?
      You can run the patch with detailed logging, see Create an MSI log file, it could explain where Windows Installer tries to find the files.

  4. somebody Says:

    Thanks this worked nicely.

  5. harlan Says:

    Hi Alexey,
    Thanks for your share.But have a question :
    can your procedures generate GAC dll update?

    • Alexey Ivanov Says:

      Hi Harlan,

      I don’t know whether it will work for DLLs in GAC. I haven’t worked with GAC, yet if I understand correctly, you don’t usually update DLLs in GAC: you install the new version of the DLL (the new assembly) and remove the old version (or probably create redirection policy so that apps use only the new version).

      Theoretically, this approach should work but I don’t know the low-level details.


Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.