Sunday, September 18, 2011

VS 2008 Setup Project Upgrade – File replacement rules for versioned and non versioned files


Recently I ran into an interesting problem in one of a .NET Windows Application's Setup project. This is a .NET 3.5 application, hence used the visual studio 2008 setup project to build MSI installer for the application. While first time installation was successful, upgrade version of the setup project failed to update few of the files.

After going through few MSDN link, got to know when you have an updated application and set RemovePreviousVersions as true in setup project “VS 2005 setup project will create MSI which completely uninstalls the old version and reinstalls the new version” but “VS 2008 will create MSI which updates the old installation based on pre defined file replacement rules”. In simplified terms below are the rules,
  1. Both the old and new files are versioned files (i.e. application’s executable, dll files)
    • If your new file is having higher version compared to old files (e.g., old dll version is 1.0.0.1 and new dll version is 1.0.0.2), old file will be replaced by new file
    • If your new file is having same or lower version compared to old files (e.g., old dll version is 1.0.0.1 and new dll version is 1.0.0.0 or 1.0.0.1), old file will not be replaced by new file
  2. Both the old and new files are non versioned files (i.e. txt files, help files)
    • Installer will compare the created time and the last modified time of the old file. If the times are not same (case when the file is modified after installation in users machine), old file will not be replaced by new file (though your new file could be different than old file). The intent of this logic is to prevent Windows Installer from overwriting files that users have modified on their machine.
    • Installer will compare the created time and the last modified time of the old file. If the times are same (case when user haven’t changed the file), old file will be replaced by new file.
A detailed combination of the rules are given in this MSDN link.

As one of my text file (non versioned) was not updated in my upgrade MSI, I ran the MSI with verbose log to understand how the Windows Installer treats my file. Below is the command to run MSI with verbose log in command prompt.
msiexec /i "SampleInstaller.msi" /l*v "d:\SampleInstaller.log"
/l tells Windows Installer to create a log, * tells it to log everything and v tells it to use verbose mode.
This is the entry in log file for one of the file which failed to update.
MSI (s) (60:8C) [09:48:51:735]: Executing op: FileCopy(SourceName=SAMPLE~1.TXT|SampleTextFile.txt,SourceCabKey=_897AF91AADD144A4A32B738927E9B501,DestName=SampleTextFile.txt,Attributes=512,FileSize=6608,PerTick=32768,,VerifyMedia=1,,,,,CheckCRC=0,,,InstallMode=58982400,,,,,,,)
MSI (s) (60:8C) [09:48:51:735]: File: C:\Program Files\Sample Application\SampleTextFile.txt;    Won't Overwrite;    Won't patch;    Existing file is unversioned but modified
The log tells that SampleTextFile.txt as “Existing file is unversioned but modified”, hence Windows Installer “Won't Overwrite;    Won't patch;”.

Ouch, SampleTextFile.txt has been modified after it was installed, hence my upgrade MSI is not updating this file. What can I do to solve this?

After googling got to know, there are no direct solutions inside Visual Studio (atleast to my knowledge in VS 2008). Here are the steps to follow to solve this issue.
  1. Download ORCA, a free utility to edit the MSI packages
  2. Open the MSI file in ORCA editor
  3. Look for Property table under Tables
  4. Add a new property named REINSTALLMODE and set its value as amus
  5. Save the MSI and close ORCA
That's It. This property REINSTALLMODE with value amus tells the Windows Installer to uninstall old files and install new files irrespective of rules (similar to VS 2005).

Here are the screen shots of ORCA editor.