Why do I care about shared component patch uninstalls?

There has been an ask from Windows Installer customers to improve the servicing story surrounding shared components. We could summarize the asks into following points: 

  1. I want Windows Installer to keep the highest version of the file across products when an update to a shared component is uninstalled.
  2. I do not want to get any source resolution dialogs while installing or uninstalling updates to a shared component.

Look at the PPT attached with this blog post to get an overview of the scenario. If you think you might ever get into a scenario described in the PPT, then you should read on.

How does Windows Installer 4.5 address this?

This section providers an overivew of how Windows Installer 4.5 addresses this

1.      Components that need the robustness that this feature provides should be marked appropriately.

2.      When installing an RTM version of that component, or when a patch carries an update to the component, we store info on the highest version of the component due to this product, irrespective of whether the component is actually updated on disk.

3.      When the file on disk is to be updated, enumerate all the product clients for the component being updated.

a.       If the cache baseline opcode is being generated for the product currently being installed Then

                                                              i.      The RTM version of the component is looked up and that becomes the source of the cache operation.

Else

                                                         i.            Verify that the component at the target location is the RTM version for this product.

                                                       ii.            Cache the component from the target location into all the component’s clients’ empty RTM caches

b.      This behavior will ensure that any patches to any of the products that carried the component will not result in any source resolution dialogs. This copy-on-write behavior also provides the optimal disk usage.

4.      When a patch is being uninstalled, we do the following:

a.       Update the registration created due to this patch in step 2

b.      If the component affected by this patch uninstall has opted for the shared component robustness functionality

Then

                                                         i.            If file version on disk > file version referenced in transform of the patch being uninstalled then,

a.       Do not down-rev the component.

                                                       ii.            If file version on disk <= file version referenced in transform of the patch being uninstalled then,

a.       Enumerate the registration created in step 2 to determine the highest versioned component and the corresponding product/patches

b.      If the component version calculated in the previous step is the same as the version of the component on disk then, we have nothing else to do.

c.       Use the the component cache created in step 3 along with the patch that can take this component to the highest version to create and copy the resultant version of the component.

c.       Else behave like Windows Installer 3.1.

How do I turn it on?

If any product marks its shared component with msidbComponentAttributesShared attribute, then this component gets this behavior irrespective of whether other products have marked it that way or not. Here’s the definition of this attribute:

//msidefs.h

enum msidbComponentAttributes

{

            ...

#if (_WIN32_MSI >= 450)

            msidbComponentAttributesShared = 0x00000800;

#endif // (_WIN32_MSI >= 450)

};

The DisableSharedComponent machine policy will let administrators turn off the opt-in behavior of msidbComponentAttributes. The following table lists possible configurations:

DisableSharedComponent

Description

0

This is the default value. When this value is set, packages can opt-in to use the Windows Installer’s shared component functionality by setting their component’s attribute to msidbComponentAttributes.

1

This value will not let any package on the machine get the shared component functionality as desired by setting the msidbComponentAttributes component attribute.

Caveats

Targeting Limitation

It needs to be called out that the assumption that this feature makes is that every patch targets the RTM version of its product. This ensures that the binary delta contains the delta for the RTM product. This can be done by building a patch to shared components such that:

1.       The patch targets RTM, by listing the RTM version of the product in the TargetImages table of the PCP.

2.       If targeting RTM image is not an option, patch authors could also use ExternalFiles table of the PCP to provide the RTM version of the file. This will ensure that the delta inserted into the patch will be able to update the RTM version of the file.

New functionality is bound to Windows Installer 3.0 Baseline Caching

It needs to be noted that this feature is available only when caching is not disabled. Also, for this feature to kick in there should be at least one MSI 3.0 minor update patch or all MSI 3.0 patches (as is the requirement for baseline caching to kick in).

Component State is Agnostic to Non-File Resources

Note that this feature doesn’t restore the registry keys while it restores the right version of a file. This assumes that the registry keys are compatible across different versions of the component.

Shared Components and Languages

Two files with the same version but for different languages are regarded as same.

A Patch That Opts-in

A patch can add the msidbComponentAttributesShared attribute and start getting the benefits of this new feature. However, when the last patch that opted in for this functionality is being uninstalled, then that transaction doesn’t get this functionality because the in-memory view of the database doesn’t contain this patch and we will behave the way when dealing with any other attribute that was patched.

Sharing across contexts

When managed (i.e., MSIINSTALLCONTEXT_USERMANAGED or MSIINSTALLCONTEXT_MACHINE) and unmanaged products (i.e., MSIINSTALLCONTEXT_USERUNMANAGED) share a component by marking it with the msidbComponentAttributesShared attribute, then while looking for other products that have a better version of the component, Windows Installer does not look across the managed/unmanaged boundaries. Same thing applies to unmanaged products installed for two different users.

 

[Author: Hemchander  Sannidhanam]
This posting is provided "AS IS" with no warranties, and confers no rights. Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm.