Changes to Package Caching in Windows Installer 5.0

Changes to Package Caching in Windows Installer 5.0

  • Comments 24

Windows Installer 5.0 is shipping in Windows 7 as part of the operating system. To address the issue where the User Account Control consent dialog is displayed with an “Unidentified Publisher”, the .msi package is cached in its entirety.

Prior to Windows Installer 5.0, installation packages, or .msi files, were stripped of their embedded cabinets – if any – when cached on the system to save space. When repairing the product, if installed files were missing then Windows Installer would attempt to use the last used source location, an application-defined location, or prompt for the installation source. While these prompts can be annoying or even difficult to resolve sometimes, they do reduce the disk space required after an installation is complete.

When Vista added UAC, elevation even for administrators by default was required. Elevation was always required for per-machine installations, but administrator accounts already ran with full privileged tokens so elevation was implicit. To add validation to this elevation prompt - aka the consent dialog - the publisher for signed packages was displayed, and “Unidentified Publisher” was displayed for unsigned packages. But during uninstall, packages would display “Unidentified Publisher” even if they were signed because their embedded cabinets were stripped thus invalidating the digital signature and so Windows Installer wouldn’t verify the cached package as shown below using Windows Installer 4.5 on Vista.

MSI (s) (DC:0C) [16:46:44:058]: MSI_LUA: Elevation required to install product, will prompt for credentials
MSI (s) (DC:0C) [16:46:44:059]: MSI_LUA: Entering Credential Request. hwnd = 1120166, MsiAction = 2, productname = Microsoft Visual Studio Team System 2008 Team Suite - ENU, version = 9.0.30729, language = 1033, manufacturer = Microsoft Corporation
MSI (s) (DC:0C) [16:46:44:059]: MSI_LUA:  (continued)... packagepath = , packagesource = , dwUpdates = 0

To resolve this issue, Windows Installer 5.0 in Windows 7 will cache the installation packages without stripping their embedded cabinets and verify the cached package as shown below using Windows Installer 5.0 on Windows 7.

MSI (s) (20:98) [16:51:25:386]: MSI_LUA: Elevation required to install product, will prompt for credentials
MSI (s) (20:98) [16:51:25:386]: MSI_LUA: Entering Credential Request. hwnd = 1116208, MsiAction = 2, productname = Microsoft Visual Studio Team System 2008 Team Suite - ENU, version = 9.0.30729, language = 1033, manufacturer = Microsoft Corporation
MSI (s) (20:98) [16:51:25:386]: MSI_LUA:  (continued)... packagepath = C:\Windows\Installer\33e5a8b.msi, packagesource = C:\Windows\Installer\33e5a8b.msi, dwUpdates = 0

But this won’t prevent prompts for source even if all files are compressed into embedded cabinets. Windows Installer 5.0 does not consider the Installer-cached .msi files to be valid source and will still resolve possible source locations or prompt as it has in the past.

Installation developers should take this into account since Windows Installer already may require so much disk space and compress files if necessary in external cabinets. Consider your servicing scenarios carefully and determine if you should cache the installation source yourself using the Source List APIs like MsiSourceListAddSource provided by Windows Installer, or just let Windows Installer use its default source resiliency behavior.

Leave a Comment
  • Please add 4 and 6 and type the answer here:
  • Post
  • The certificate was made by Verysign.  It is used with the signtool and the installer shows correctly the company at the time of installing.

    It displays the unknown publisher at the time of uninstall only, in Vista and Win7 with all the updates.

    Seems that the cached copy of the msi to uninstall has the signature but it says it is corrupted.

  • @allanCm, that behavior is by design for Vista but you should not see it with Win7. Did you install with a customization transform? If you can set the Logging system policy for Windows Installer (see MSDN), you can post it and I can have a look why.

  • Hello,

    I noticed that when I install a patch (.msp package) on a basic MSI project, a folder is created under the folder:

    "c:\windows\Installer\$PatchCache$\Managed\"

    containing some files.

    Anyway I noticed a difference between installation of the MSP package on Windows XP, windows Vista and installation of the MSP on Windows Seven:

    On Windows XP and Vista, not all binaries that were changed by the hotfix are cahced into the "c:\windows\Installer\$PatchCache$\Managed\" folder.

    On Windows Seven, all the binaries that were changed by the Hotfix were cached on that folder, but some of them are from the MSI project (the RTM), and others from the hotfix. - which seems very weird behavior.

    The mix between the binaries version after uninstalling the hotfix causes a run-time problem. as I think the problem starts on the hotfix install which stores some binaries from the hotfix and others from the MSI project inside the "c:\windows\Installer\$PatchCache$\Managed\" folder. As I expect - all files stored inside the mentioned folder should be from the MSI project (the original files).

    Could you explain to me why this happens and how could I solve the problem?

    Thanks in advance,

    Donna

  • @Donna.Makhoul, files are only placed in the patch cache when they are overwritten or delta-patched. If the files were not overwritten by the patch (because the component was installed, or the file was already updated by the same or different patch for another product) they are not copied to the baseline cache. There's many factors that can affect this.

    Patch uninstall should be consistent, though. But without seeing verbose install logs of both RTM and the patch I can't say anything for sure.

  • I have a product A and Product B. Both consume a Merge module C and install this merge module in their own Product's folder. Now when i do a minor update of for Product A, merge module components are getting upgraded and at the same time older files related to components are cached to C:\WIndows\Installer\$Cached$\Managed\.. folder. After this when i upgrade Product B, the installer logs show that merge module component files are overwritten, but the source of these files is shown as C:\WIndows\Installer\$Cached$\Managed\.. folder. Hence eventhough Installer logs show that files are overwritten, since the source is the C:\WIndows\Installer\$Cached$\Managed\..folder which has previous version files, merge module component files are not getting upgraded for Product B. Is there a way to prevent this from MSI.

  • @Uday, MSMS are merged into the MSIs (hence the name) so that they install like any other files in A and B is expected and by design. The MSM itself is basically lost at build time. At install time, the components look like any other components in an MSI. So when youre installing B that merged the same MSM (you didn't mention if it was a newer version or not) the files would be the same version. Already remember that unversioned files are always overwritten if unmodified (i.e., modification timestamp == creation timestamp).

  • Why isn't there a Microsoft Knowledgebase item for this?

  • @Mark, it's a feature and does not break back-compat. Those types of issues typically don't go into a KB article.

  • Hello,

    I'm working on a patch for our product. And I noticed that non-versioned files are not cached in "C:\Windows\Installer\$PatchCache$" when they are overwritten during the patch installing. Therefore I get prompt to resolve source location when I try to uninstall the patch. I checked this on Windows Server 2003 and Windows 7, behavior is the same in both cases: non-versioned files are not cached and versioned files are cached during patch install.

    Could you explain me is it proper behavior of windows installer? It's very strange I think.

    Here are some parts of l*v log from patch installing (Test.Wix.txt is non-versioned file, Test.Exe.exe is versioned):

    ---------

    MSI (s) (84:E0) [18:26:26:814]: Patch Modified Files List:

    MSI (s) (84:E0) [18:26:26:814]: File = Test.Wix.txt: Final State = Install

    MSI (s) (84:E0) [18:26:26:814]: File = Test.Exe.exe: Final State = Install

    ...

    Action start 18:26:26: InstallValidate.

    MSI (s) (84:E0) [18:26:26:861]: Feature: Test.Wix; Installed: Local;   Request: Reinstall;   Action: Reinstall

    MSI (s) (84:E0) [18:26:26:861]: Component: Test.Wix.txt; Installed: Local;   Request: Local;   Action: Local

    MSI (s) (84:E0) [18:26:26:861]: Component: ConnnProp.dll; Installed: Local;   Request: Local;   Action: Local

    MSI (s) (84:E0) [18:26:26:861]: Component: Test.Exe.exe; Installed: Local;   Request: Local;   Action: Local

    MSI (s) (84:E0) [18:26:26:861]: Component: __Test.Wix.txt65; Installed: Null;   Request: Local;   Action: Local

    MSI (s) (84:E0) [18:26:26:861]: Component: __Test.Exe.exe65; Installed: Null;   Request: Local;   Action: Local

    ...

    Action start 18:26:28: InstallFiles.

    MSI (s) (84:E0) [18:26:28:955]: Patch Modified Files List:

    MSI (s) (84:E0) [18:26:28:955]: File = Test.Wix.txt: Final State = Install

    MSI (s) (84:E0) [18:26:28:955]: File = Test.Exe.exe: Final State = Install

    MSI (s) (84:E0) [18:26:28:955]: Note: 1: 2205 2:  3: MsiPatchOldAssemblyFile

    MSI (s) (84:E0) [18:26:28:955]: Note: 1: 2228 2:  3: MsiPatchOldAssemblyFile 4: SELECT `MsiPatchOldAssemblyFile`.`Assembly_` FROM `MsiPatchOldAssemblyFile` WHERE  `MsiPatchOldAssemblyFile`.`File_` = ?

    MSI (s) (84:E0) [18:26:28:955]: Note: 1: 2205 2:  3: Error

    MSI (s) (84:E0) [18:26:28:955]: Note: 1: 2228 2:  3: Error 4: SELECT `Message` FROM `Error` WHERE `Error` = 1302

    MSI (s) (84:E0) [18:26:28:955]: Note: 1: 2205 2:  3: MsiSFCBypass

    MSI (s) (84:E0) [18:26:28:955]: Note: 1: 2228 2:  3: MsiSFCBypass 4: SELECT `File_` FROM `MsiSFCBypass` WHERE `File_` = ?

    MSI (s) (84:E0) [18:26:28:955]: Note: 1: 2205 2:  3: MsiPatchHeaders

    MSI (s) (84:E0) [18:26:28:955]: Note: 1: 2228 2:  3: MsiPatchHeaders 4: SELECT `Header` FROM `MsiPatchHeaders` WHERE `StreamRef` = ?

    MSI (s) (84:E0) [18:26:28:955]: Caching Test.Exe.exe from C:\Program Files (x86)\Test.Wix\Test.Exe.exe for baseline 0

    Action ended 18:26:28: InstallFiles. Return value 1.

    ---------

    Here docs.google.com/.../edit you can download full logs and binary files.

    Thanks in advance.

Page 2 of 2 (24 items) 12