QA uncovered a problem when testing our patches for .NET Framework 1.0 and 1.1 lately that will ship with an updated binary that now runs as a service under Windows NT platforms. The file version was incremented but in the log file we saw the following:

MSI (s) (3F:2B): Executing op: FileCopy(SourceName=netfxupd.exe|netfxupdate.exe, SourceCabKey=DDPatch.UpdateUtilFile, DestName=netfxupdate.exe, Attributes=4096, FileSize=106496, PerTick=32768,, VerifyMedia=1,,,,,CheckCRC=0,Version=1.0.3705.1,Language=0,InstallMode=42205184,,,,,,)
MSI (s) (3F:2B): File: D:\WINNT\Microsoft.NET\Framework\v1.1.4322\netfxupdate.exe;  Won't Overwrite;  No patch;  Existing file is of an equal version

The CAB embedded in the MSP did contain the right version — 1.0.3705.3 — so why was MSI seeing the older version?

This is the result of a known problem before MSI 3.0. That file and its containing component are ones we've been adding since the first patch you installed for .NET Framework 1.0 and 1.1. They are files to support patching the Framework. INSERT opcodes are generated for the QFE and SP transforms that target RTMs as well as all SPs (since they all target RTMs). The INSERT opcode is generated because the RTM doesn't contain those files. It's important to note that currently our SPs target other SPs, so this does not cause a problem if you only have another SP installed and not a QFE from the Download Center or Windows Update.

When the transform is applied the new insert fails silently if another QFE patch is already installed because the MSITRANSFORM_ERROR_ADDEXISTINGROW (0x00000001) error condition is set when creating the transforms, which you can see from the Character Count summary property for the transform (MST) file as 0x001F0922. We could unset this flag, but then many patches would simply fail to install entirely.

A workaround for this problem was introduced in MSI 3.0. If the MSP contains the MsiPatchSequence table the patch is treated as a 3.0-style patch. In this case, if an INSERT opcode fails an UPDATE is attempted second before failing the transform of the target row. The inclusion of the MsiPatchSequence table means, however, that you must also implement 3.0-style sequencing. If you must still support MSI 2.0 clients you must support 3.0-style sequencing in addition to 2.0-style obsolescence, which lists the patch GUIDs to replace in the Revision Number summary property. Any patches with an empty MsiPatchSequence table are treated as invalid and will not be installable under MSI 3.0 and newer, erring out with the text "No valid sequence could be found for the set of patches.".