How Windows Installer handles file replacement logic for versioned and unversioned files


I ran into an interesting problem yesterday where a team had built an MSI-based setup package, and they were seeing sporadic problems where some of the files failed to install.  They enabled Windows Installer verbose logging and this is an example of an entry for one of the files that was failing to install:



MSI (s) (B4:4C) [11:30:07:906]: Executing op: FileCopy(SourceName=eulatxt|eula.txt,SourceCabKey=FILE1,DestName=eula.txt,Attributes=512, FileSize=29239,PerTick=32768,,VerifyMedia=1,,,,, CheckCRC=0,,,InstallMode=58982400,HashOptions=0, HashPart1=-1713153497,HashPart2=58557210, HashPart3=1046945815,HashPart4=871163290,,)
MSI (s) (B4:4C) [11:30:07:906]: File: C:\WINDOWS\system32\eula.txt; Won’t Overwrite; Won’t patch; Existing file is unversioned but modified


After I saw this, I took a look at the MSI package and I found that this MSI was divided into one component per file, and each component used the one file that it contained as the key path.  This led me to understand the root cause of this issue.  Windows Installer has a specific set of rules for file versioning and how it decides when to replace files when they already exist in the destination location.  Here are the possible permutations for file versioning:



  • In the case when the source and destination files are both versioned files, these rules are straightforward – if the key path file does not exist in the destination location or if it exists in the destination location and it is of a lower version, Windows Installer will install the component (and all of the files in it, including the key path).  If the key path file exists in the destination location and it is of an equal or higher version, Windows Installer will not install the component but instead only reference counts the component.  It becomes trickier when only one of the files is versioned or neither of them are.
  • In the case when only one file is versioned, Windows Installer will install the component (and all of the files in it, including the key path file) if the source file is versioned and the destination file is not (meaning it will replace an unversioned file with a versioned one).  It will not install the component but instead only reference counts the component if the source file is unversioned and the destination file is versioned (meaning it will not replace a versioned file with an unversioned one).
  • In the case when both files are unversioned and have file hashes (as in the scenario I was debugging yesterday), Windows Installer will compare the created time and the last modified time of the destination file.  If the times are the same, Windows Installer will compare file hashes of the source and destination files.  If the file hashes are different, Windows Installer will install the component (and all of the files in it, including the key path).  If the file hashes are the same, Windows Installer will not install the component but instead only reference counts the component.  This means that if the key path file already exists in the destination location but has been changed sometime after it has been created, Windows Installer will not update this file, even if it is carrying a different copy of the file as part of the setup package.  The intent of this logic is to prevent Windows Installer from overwriting data files that customers may have modified on their machine before running setup

  • In the case when both files are unversioned and do not have file hashes, Windows Installer will compare the created time and the last modified time of the destination file.  If the times are the same, Windows Installer will install the component (and all of the files in it, including the key path).  If the times are different, Windows Installer will not install the component but instead only reference counts the component.

This particular MSI I was investigating was trying to update a text file named eula.txt in %windir%\system32.  In some test cases, the file did not exist, in some cases it existed and was identical and in some cases it existed and was different.  The 3rd and 4th versioning rules above explains why this problem would only occur on some test machines but not others.  This illustrates one of the problems with using an unversioned file as the keypath for a component, especially if the file could be shared by other products on the system.  The solution I recommended to the team hitting this problem was to move this eula.txt file to be installed as part of another component that installed to %windir%\system32 and had a binary file as a key path.  In general you have to be careful about installing multiple files in one component (because of the Windows Installer component rules), but in this case it is a simple text file, which mitigates some of the drawbacks of including multiple files in a component (complicated servicing and incorrect uninstall behavior being the main risks here).


<update date=”9/6/2005″> I listed the logic incorrectly that Windows Installer uses when both the source and destination file are unversioned.  I have updated the 3rd bullet above based on the feedback in Stefan’s comment. </update>


<update date=”4/29/2008″> MSDN links in this post were broken, so I updated them to work again. </update>


 

Comments (53)

  1. Tom Busmire says:

    Aaron – just to point out that the ref counts are only updated if the msidbComponentAttributesSharedDllRefCount bit flag is set (set the Attribute column of the Component table to 0x0008) or if the ref count already exists. See http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/component_table.asp

  2. Vince says:

    I’m getting error un install MS SQL Native CLient from Beta 1, any I deas on how to remove this sucker, I tried the vs_uninstall tool, msizap and add remove programs, not is this order, none of these approaches rids me of this cancer.

    HELP!

    V.

  3. astebner says:

    Hi Tom – your comment is true for shared DLL ref counts (which are stored in HKLMSoftwareMicrosoftWindowsCurrentVersionSharedDlls. Windows Installer also keeps an internal ref count for component IDs of all components that are installed on the system, regardless of whether or not it installs the files contained in those components, and regardless of what the component attribute settings are in the Component table of your MSI.

  4. astebner says:

    Hi Vince – I’m sorry for the hassles you’re facing while trying to uninstall SQL 2005. Can you please gather the SQL log files located at %ProgramFiles%Microsoft SQL Server90Setup BootStrapLOGFiles*.*, zip them up and send them to me at aaronste (at) microsoft (dot) com so I can take a more detailed look at what might be causing this uninstall issue?

  5. Aaron,

    in your case no. 3 (both files are unversioned) in a first step Windows Installer DOES NOT compare source file with destination file. Instead it ONLY looks at the destination file and compares its "created" and "modified" dates. If the modified date is more recent – which means the file was edited by the user after it was created/installed – it will never be overwritten.

    Only if the modified date is less recent or equal than the created date of the destination file Windows Installer will compare the hashes of the two files. If it finds that the files are different, it will install the file (regardless of the date of the source file). This hash comparison was added to avoid unnecessary copy operations on files that are binary identical, thus minimizing requests for the original CD.

    This means (and that’s often confusing people) that for unversioned files the date of the file in your setup package doesn’t matter. Actually, Windows Installer doesn’t even know about the date, as the File table only stored version and size, but not date.

  6. astebner says:

    Hi Stefan – thank you for the clarification. I will update the text of the main post to reflect this.

  7. Hochi says:

    This might be a little off, but i was wondering how i can run two installers at the same time, cause i need one to call on a java installer which sadly is an exe file so i cant decompile it. thanks for the help

  8. astebner says:

    Hi Hochi – You cannot run 2 Windows Installer-based setups at the same time.  In this scenario, you will need to use a setup.exe bootstrapper/chainer to launch each of the MSIs.  You should include logic in the bootstrapper to detect if the MSI is already installed on the machine and then conditionally launch the MSI if it is detected as being needed.

  9. Mike says:

    Do you have any suggestions about how to deal with .NET application configuration files (e.g. SomeApp.exe.config)? We use these to store version redirects for both .NET applications and COM apps which use .NET assemblies via Interop.

    Since these are not versioned and not changed by the user, the Windows Installer will happily overwrite a newer config file with an older one.

    I cannot use the EXE as a companion file, since a version change in any of the 4 dependent DLLs listed in the config file could require a config file change without recompiling the EXE.

  10. astebner says:

    Hi Mike – Unfortunately, you have found a case that Windows Installer does not handle very well.  You may need to author this logic as a custom action to workaround possible cases where a newer file could be overwritten by an older file.  If you are using WiX for your setup (http://wix.sourceforge.net), it has a built-in custom action that you can use to modify XML data.  Check out http://www.tramontana.co.hu/wix/lesson5.html#5.11 for more information.

  11. Kevin says:

    I am trying to get a MSI to update the bitmap we use as the background.  However, the MSI does not seem to want to replace the file the new bitmap has a later modified date then the one currently on the system.  It installs the bitmap if it does not exist.

  12. astebner says:

    Hi Kevin – It seems like the BMP should have been updated in that scenario.  Do you have a verbose log file from that installation scenario that you could send me?  If not, you can use the steps at http://blogs.msdn.com/astebner/archive/2005/03/29/403575.aspx to gather it and you can contact me at Aaron.Stebner@microsoft.com and send it to me so I can take a look.

  13. One of the features included in the WiX v3.0 source files included in the C# project template in the

  14. One of the features included in the WiX v3.0 source files included in the C# project template in the

  15. vrapp says:

    Curious, does Installer have equivalent provisions – not to remove what’s modified – for other objects – registry entries, ODBC elements, .ini setttings, etc.? it looks like it’s only for the files. For registry settings, specifically, it looks like it does not. This is important not as much during removals as during the upgrades.

  16. astebner says:

    Hi VRapp – Windows Installer has a pretty specific set of component rules that define what will be replaced in what scenarios.  The key path used for the component defines what replacement logic to use – a key path can be a versioned file, an unversioned file, a registry key or a folder.  Each type of key path has different logic for determining when to install the component.

    There is helpful information about the Windows Installer component rules at the following links:

    http://msdn.microsoft.com/library/aa368007.aspx

    http://blogs.msdn.com/robmen/archive/2003/10/04/56479.aspx

    http://blogs.msdn.com/robmen/archive/2003/10/18/56497.aspx

  17. DeepuAbrahamK says:

    Hi Aaron,

    In the 3rd scenario, I am trying to patch some files.I have a case where the files are getting copied because it uses the hash files for resolving, but the timestamp of the patched file is showing incorrect.The file in question is not a binary file and hence does not have any version number.I still shows the wrong timestamp even after putting a binary file as the Key path.Is this a known limitation which Microsoft is already aware of?

    Best Regards,

    Deepu

  18. astebner says:

    Hi DeepuAbrahamK – I’m not sure I understand the scenario that you’re describing.  What do you mean when you say that the timestamp of the patched file is showing incorrect?  The Windows Installer unversioned file replacement logic doesn’t use the timestamp of the file – it uses the creation time and the last modified time.

    Also, when you say patch, do you mean that you have installed an MSI and then are building a patch for it, or do you have an MSI that is attempting to update a file that already exists on the system?

    Also, just to confirm, are both the original file and the new file unversioned, and is the unversioned file the keypath of the component in question, and does the unversioned file have a file hash stored in your MSI?  If so, the replacement logic uses the flow chart at http://msdn.microsoft.com/en-us/library/aa370532.aspx, so I’d suggest reviewing the exact logic there to see how that matches up to the files in your scenario.

  19. DeepuAbrahamK says:

    Hi Aaron,

    When I say timestamp, I am talking about the the date modified of a file.

    I have installed ‘x.msi’ which has ‘a.exe’,’b.txt’ and ‘c.txt’ now I need to update ‘a.exe’ and ‘b.txt’ using ‘y.msp’ after installation the ‘a.exe’ gets replaced and it shows the correct last modified time but ‘b.txt’ is showing the currunt time of installation. (looks like the ‘b.txt’ is getting replaced but it shows the current time of installatioin).Both original file and the new file are unversioned but has a hash stored.I have given the key path of ‘b.txt’ as ‘a.exe’ but it doesn’t seems to be working.

    I am applying the patch programmatically using ACTION=ADMIN mode. Before calling MsiInstallProduct, I create few dummy files ‘a.exe’,’b.txt’ & ‘c.txt’ in the based in the IDX files which I have.So that has creation and modified time are same.Does this cause any problem?

  20. astebner says:

    Hi DeepuAbrahamK – How is your MSI componentized?  For example, are the 3 files in their own components, and what is the exact key path of each component?  

    Also, in this type of scenario, it usually helps to install the patch with verbose logging enabled and look at the log file for information about why files are or are not being replaced.  Can you try that and see if that helps you narrow this down?

  21. DeepuAbrahamK says:

    From the component i can see,

    a.exe {96E4B454-D21A-4C21-A03E-8C9A42147466} INSTALLDIR 0 a.exe

    d.exe {88A8C534-C813-44A5-BBA4-C6FCF53CABB2} INSTALLDIR 0 d.exe

    I cannot see ‘b.txt’ & ‘c.txt’ in the component field.

    From the file field I can see,

    a.exe a.exe a.exe 2900342 9.2.14.550 1033 0 11

    b.txt d.exe b.txt 515215 0 10

    After the verbose logging I got the following; Here is the excerpt:

    38:906]: Executing op: SetSourceFolder(Folder=1XXYYY)

    MSI (s) (28:FC) [12:09:38:906]: Executing op: FileCopy(SourceName=b.txt,SourceCabKey=b.txt,DestName=b.txt,Attributes=0,FileSize=515215,PerTick=32768,,VerifyMedia=1,,TotalPatches=1,PatchHeadersStart=23,,CheckCRC=0,,,InstallMode=58982400,HashOptions=0,HashPart1=-1531131926,HashPart2=-1084641065,HashPart3=577319224,HashPart4=-1954717788,,VariableStart=BinaryData)

    MSI (s) (28:FC) [12:09:38:906]: File: C:Documents and SettingsmyuserLocal SettingsTempMyTemp.tmpPatchPathxxyyyb.txt.tkd; Won’t Overwrite; Won’t patch; Existing file is unversioned but modified

    MSI (s) (28:FC) [12:09:38:906]: Executing op: FileCopy(SourceName=a.exe,SourceCabKey=a.exe,DestName=a.exe,Attributes=0,FileSize=2900342,PerTick=32768,,VerifyMedia=1,,TotalPatches=1,PatchHeadersStart=23,,CheckCRC=0,Version=9.2.14.550,Language=1033,InstallMode=58982400,,,,,,,VariableStart=BinaryData)

    MSI (s) (28:FC) [12:09:39:375]: File: C:Documents and SettingsshaileshLocal SettingsTempMyTemp.tmpPatchPathxxyyya.exe; Won’t Overwrite; Will patch; Existing file is a lower version

    Sorry for the long description.

  22. astebner says:

    Hi DeepuAbrahamK – The information in the file table means that you have included b.txt in the same component as d.exe, and d.exe is the key path of the component.  That means the component will only be updated if you update d.exe, but that’s ok in this case because it sounds like you’re updating both d.exe and b.txt.

    The relevant line in the log file is this one:

    MSI (s) (28:FC) [12:09:38:906]: File: C:Documents and SettingsmyuserLocal SettingsTempMyTemp.tmpPatchPathxxyyyb.txt.tkd; Won’t Overwrite; Won’t patch; Existing file is unversioned but modified

    It is saying that the copy of b.txt installed on your computer is unversioned but has been modified (meaning that the created time of that file is different than the last modified time).

    You’ll need to investigate how the original copy of b.txt on your system is being modified prior to attempting to install this patch.

  23. DeepuAbrahamK says:

    Hi Aron, I have noticed one thing here from the file field of the main MSI,

    b.txt d.exe b.txt 515215 0 10

    but the .MSP has only 2 files which are a.exe and b.txt, so I have edited the row in the file field as

    b.txt a.exe b.txt 515215 0 10

    After editing also I have not able to get the correct time on the patched file.Looks like the file is getting replaced but it somehow retains the current time of patch installation.

    Also I would like to mention that I create a zero kb dummy files (a.exe,b.txt,c.txt,d.exe) in the folder before I patch with latest a.exeand b.txt.Does it make any difference?

    Thanks,

    Deepu Abraham K

  24. DeepuAbrahamK says:

    It says that the "Existing file is unversioned but modified" does it mean that the hash values in the files are different. How does it know that the files has modified? Here in my case the creation and the modified time are the same?

    Thanks

    Deepu

  25. astebner says:

    Hi DeepuAbrahamK – The behind-the-scenes logic used by Windows Installer in this type of scenario is described in the MSDN topic at http://msdn.microsoft.com/library/aa370532.aspx.  Keep in mind that the only file that the created and last modified time matters for in this type of scenario is the file that is already on the hard drive at the destination location (and not the one in the MSP).

    I don’t understand your question about the main MSI and the MSP.  What you are editing is the component that owns the file b.txt.  There should not be any reason for you to need to change the component that owns this file, and you also should not be changing component composition in a patch like that.  If you need to update your b.txt in a patch, and the original MSI includes b.txt in the component with d.exe, then you also need to update d.exe in your patch since d.exe is the key path of the component that owns b.txt.

  26. DeepuAbrahamK says:

    Yes, My application follows the entire steps as mentioned in the link correctly.The only difference which I am seeing is that the unversioned file is getting copied but the file time gets changed to same as installation time.

  27. astebner says:

    Hi DeepuAbrahamK – Which file time is being updated to the same time as installation time?  Is it the creation time, the last modified time, or both?

  28. DeepuAbrahamK says:

    Its the ‘b.txt’ (file is unversioned) which gets the last modified time only as that of installation time.The ‘a.exe’ gets copied correctly and shows the correct time (this file is versioned).So only the last modified time of b.txt is updated to the same time as installation time.

  29. astebner says:

    Hi DeepuAbrahamK – Just to make sure I’m understanding your scenario correctly, what you’re seeing is that the unversioned file ends up with a last modified time that matches the install time (and not the time the file was modified in your build process).  However, the versioned file ends up with a last modified time that matches the time the file was modified in your build process (and not the install time).  Is that accurate?

    Is the creation time for b.txt also set to the install time so that the creation time matches the last modified time?  If so, I think that makes sense from Windows Installer’s perspective – it is resetting the creation and last modified time so that the next time it needs to update the file, it can tell whether or not the file has been modified by the user.

  30. DeepuAbrahamK says:

    Yes, You are right regarding the first paragraph.

    But the creation time for b.txt is not same as that of the last modified time. Does MSIEXEC modify the file?

  31. DeepuAbrahamK says:

    Hi Aron, One more question, Is it necessery to have the old files or original installed files in the INSTALLDIR before I patch? Since I have the file names of the original installed files,I create those files (0 kb files) inside the INSTALLDIR using my code so that MSIEXEC will not shout.Does this cause any problem?

  32. astebner says:

    Hi DeepuAbrahamK – Typically a patch is an update to existing files that your product previously installed.  I would expect your original MSI to have installed those files to the user’s system before your patch attempts to update them.  Creating 0 byte files can be helpful for testing purposes in some cases, but you should focus your patch testing effort on real-world customer scenarios (install your product, which includes version 1 of b.txt, then install your patch, which includes version 2 of b.txt).

    I don’t know enough about the internal implementation details of Windows Installer to answer your other question (does MSIEXEC modify the file).  I would expect the modified time of the file to match the time that your build process stamped on it, but that doesn’t appear to be the case based on your experience.  I’m not sure the exact modified time that the file ends up with in the end matters for this scenario though.

  33. DeepuAbrahamK says:

    Hi Aron,

    Thanks for your help & patience, much appreciated.I have kind of got to the bottom of the problem. There was a callback set in the API MsiSetExternalUI(INSTALLUI_HANDLER,..)and this was doing the trick.While installing/patching the application, callback kicks in.I have changed few things in the callback and it did the trick after I tried to set the date and time of files to be patched as the original installation date and time.While patching on that it patched correctly with the same date and time as that of the build date.

    Thanks again,

    Deepu Abraham K

  34. saravanan says:

    i am working in Microsoft Patch file creation for my application setup.

    i have used msimsp exe to create patch file and it is created sucessfully without error but MSP is not overwrite the existing application exe. if older application exe is available in installation path then MSP ignores latest exe installation.

    if i rename older exe then MSP installs latest exe in application path.

    Please let me know how to resolve this issue.

    Regards,

    P. Saravanan

  35. astebner says:

    Hi Saravanan –  The first thing I’d suggest doing is gathering a verbose log file from the installation attempt where you apply the MSP and it doesn’t update your application file.  The verbose log will typically give you more information about what Windows Installer is doing behind the scenes and it can be helpful to narrow down root causes of this type of issue.

  36. Deward_Zang says:

    Hi Aaron,

    This information is much helpful! I meet similar issue that some unversioned files are modified after installation and they are not updated during applying patch as result.

    My question: Is there a way to make all unversioned files in patch update directly no matter whether their Created date and Modified date are different or not?

    My current workaround is to set REINSTALL=FeatureToUpdate and REINSTALLMODE=amus during applying patch. This causes the source installation files are required and all of then are reinstalled. This is not good…

    Thanks,

    Deward

  37. astebner says:

    Hi Deward_Zang – I don't know of a way to force a patch to always update unversioned files but not to also do the same for versioned files.  The "a" value in the REINSTALLMODE property will cause all files to be updated regardless of existing files, but that is generally a bad thing to do as you noted because it would cause versioned files that are lower versions than the ones on the computer to be downgraded.

    Why do you need to always update unversioned files?  If this is a requirement in your scenario, you may need to revisit how you are componentizing your MSI in the first version so that you don't rely on unversioned files being component key paths.

  38. Kiran Hegde says:

    During replacement of versioned files, is the version of the file on the disk actually checked or is the version information read from the msi file?

    Remember, MSI is declarative.

    I have a situation where the version column in the MSI  has been populated for an unversioned file. When i say unversioned file, it means to say that if you were to check the file properties, you would not see a version. Now i build a patch for this msi. In the upgraded msi, the version is again retained the same as in the target msi.

    When the patch is applied, the file is not replaced stating that the version of the file on the disk is the same as the one contained in the patch.

    **This means to say that windows instaler service references the version from the catched msi package rather than actually reading the version of the file on the disk at install time**.

    Could you please confirm this?

    Regards,

    Kiran Hegde

  39. astebner says:

    Hi Kiran Hegde – I thought that Windows Installer would look at the files on disk in this type of scenario and not rely solely on the data in the MSI.  However, I don't have access to the Windows Installer source code, so I don't know that for sure.

    What is the exact text that you see in the verbose Windows Installer log file in your patch install scenario?

  40. Kiran Hegde says:

    I see the following text:

    ;      Won't Overwrite;                Won't patch;      Existing file is of an equal version

  41. Kiran Hegde says:

    FileCopy(SourceName=<file name>,SourceCabKey=<file name>.2AE7ACF6_3BDA_4F10_969B_D26E431A3BFF,DestName=<file name>,Attributes=4096,FileSize=77824,PerTick=65536,,VerifyMedia=1,,,,,CheckCRC=0,Version=6.0.0.0,Language=1033,InstallMode=8650752,,,,,,,)

    MSI (s) (BC:14) [12:06:39:182]: File: <desination file path>o;      Won't Overwrite;                Won't patch;      Existing file is of an equal version

    This is what i see.

  42. astebner says:

    Hi Kiran Hegde – I'm not sure how to explain this behavior.  It is possible that MSI is only doing this for incorrectly marked files (such as an unversioned file marked with a version in the MSI), and/or it might only do this for patch install scenarios.

    Do you have any cases where a versioned file is marked with a version number that is incorrect in the MSI to test out this theory?

    You will probably need to post a question on a Microsoft Windows Installer forum and/or contact Microsoft Technical Support to get an official answer about what behavior to expect in this type of scenario.

  43. Kiran Hegde says:

    Hello,

    I am facing a strange issue where the files are not copied after a patch installation.

    Up until now, we were delivering updated versions of our product using .msi(major upgrades). However, now we want to ship our updates using  .msp files.

    There are around 5 files in 5 different components. Each of these files are unversioned and are the key files for the respective components.

    Somewhere during the product lifecycle, someone introduced entries for these files in the RemoveFile table, so that the latest version of the files is always copied during the upgrade process. I am not sure as to why this was requiered, as  the File hashing for unversioned files should have allowed upgrading of these files, without requiring an explicit removal(using RemoveFile table) and installation using the InstallFiles . This was  done when the upgrades were delivered using msi files.

    All was working.

    Now , we have decided to release updates to our product using a  msp(patch ) file. However, it's surprising that the files are not  re-installed during apatch.

    i.e the remove file table deletes these files and the InstallFiles standard action does not restore them. I would have expected these to be restored as they are they key files for the respective components and missing key files to be restored.

    The windows installer log files indicates that the corresponding components are  marked for installation.

    I also see the following snipped in the log file:

    Allowing installation of component: {199327E3-7FBE-4D9F-8DED-38DBDEDEEC03} even though a modified unversioned keyfile exists and file versioning rules would disable the component

    Is it because windows installer detected that the existing file on the disk was modified and decided not to replace it-atleast thats what the log message indicates. I did take alook at the files on the disk before running the patch and found that none of them were modified.

    Could someone explain to me as to why this behavior?

    Regards,

    Kiran Hegde

  44. Kiran Hegde says:

    Could someone kindly comment about the previous comment?

    Thanks,

    Kiran Hegde

  45. astebner says:

    Hi Kiran Hegde – I haven't run into a scenario like this before, so I'm not sure how to explain what is happening.  The log entry that you listed indicates that Windows Installer thinks that the keyfile has been modified, so maybe that has something to do with it?  Are there any other entries later in the verbose MSI log file related to this component ID that might help explain this behavior?

  46. Matt W says:

    So, I have an unversioned component key file (anotherApp.msi file used for update of another app).  It seems the logic to determine overwrite just looks at the create and modified date of a pre-existing anotherApp.msi on the target system.  The fact that it is the key doesn't call in any special overwrite logic, but only determines if the other files that may be in that component are installed, correct?

  47. astebner says:

    Hi Matt W – If an MSI has a component with an unversioned file as a key path, Windows Installer will compare the created time to the last modified time for that file.  If they are equal, then Windows Installer will replace the file and will update all other files in the component.  If they are not equal, then Windows Installer will not replace the file and will not update all other files in the component.

    If you see behavior that doesn't match what I described above, then I recommend looking at the verbose MSI log file to narrow things down further.

  48. Daivd says:

    The last case: none has version and hash.look at this:

    msdn.microsoft.com/…/aa370531.aspx

    It seems your conclusion is wrong. If create dates and modifed time are different, the replacement will happen.

  49. astebner says:

    Hi Daivd – My blog post is saying the same thing as the flow chart in the MSDN topic you linked to.  The flow chart says "Are the Created and Modified dates of copy-B different?"  The No answer is "Replace copy-B with copy-A."  That means the replacement will happen if created and modified dates are *not* different (or as I worded it in my blog post, if they're the same).

  50. Shawn says:

    What about the case where you are trying to downgrade? My company wants me to setup our installer to be able to downgrade the product if needs be. In the past they have put out a product version that didn't work for some of our and the customer had to uninstall the new version and install the older version. With our new product they want the customer to just be able to install the old version over the new version. What I am seeing though is that the versioned files on the system are not being removed and replaced with the older, lower versioned files.

    With windows installer is it even possible to do a downgrade?

  51. astebner says:

    Hi Shawn – Windows Installer does not allow installing an older version of a file over the top of a newer version of a file. You would have to uninstall the newer version of the file first in order to be able to install the older version of the file.

    Depending on your scenario, it might be an option to author your new MSI to do a major upgrade of the old MSI and automatically uninstall the old MSI behind the scenes as a part of its install process.  You can do a web search for "Windows Installer major upgrade" to find more information about that option to see if that might work for you.