none
MSI RemovePreviousVersions permanently removes reg keys when a newer MSI version is installed

    Question

  • Hello Everyone,

    I am having an issue with an MSI (created using VS2010) that keeps removing registry keys when a new version of the MSI is installed.

    Lets say you have an MSI that adds a registry key (setting its DeleteAtUninstall property to true, and its AlwaysCreate propery to true)

    You want the MSI to automatically remove previous versions, so you set the following property at MSI level:

    RemovePreviousVersions = true

    The MSI is built, and installed on a machine, and that registry key is created successfully - great.

    Then however, you want to release a new version of that MSI - for whatever reason.

    You increment the Version number of the MSI, plus generate a new ProductCode, but keep the UpgradeCode so that Windows Installer knows what product to remove.

    You then install this MSI

    (in my case using the command line call msiexec.exe  /i "c:\msi\Sales Progression.1.2.19.msi" /qn /norestart)

    The MSI installer completes with a return code of 0 indicating a success.

    At this point, I expected (incorrectly) that both the original reg key plus the new one would be created.

    In reality, they have both been removed.

    When I look at the verbose install log, the "RegAddValue" calls are made FIRST, THEN the "RegRemoveValue" calls are made after that.

    What am I doing wrong?

    Thanks for any help in advance!

    Kind Regards,

    Matt

     

    Friday, September 24, 2010 2:25 PM

Answers

  • Hi Matt,

    The reason your upgrade is behaving this way has to do with component reference counting and product removal timing.

    You need to decide what type of upgrade you will be performing.  If you are always upgrading the same locations then the most efficient method is to have your all your MSI files share component guids for the same resources and adjust when you call RemoveExistingProducts action to after InstallFinalize.

    If you are changing folder locations and some registry values are shared between versions then you are likely going to want to uninstall the old product first and then install the new product.  In this case you don't need to worry about component guids (as much) and you can place RemoveExistingProducts action early in the Execute sequence (InstallValidate).

    Unfortunately I don't have VS2010 handy so I can't tell you what option to use to adjust this location of this action.  But you can always adjust the MSI itself through a post-build script. I suggest getting it working manually using the orca msi editor first.

    If you want to read up on what I am talking about-
    Component Reference Counting: http://robmensching.com/blog/posts/2003/10/18/Component-Rules-101 
    RemoveExistingProducts action: http://msdn.microsoft.com/en-us/library/aa371197(VS.85).aspx

    Sincerely,
    Adrian Accinelli

    • Marked as answer by MattDendle Tuesday, September 28, 2010 8:01 AM
    Friday, September 24, 2010 4:28 PM
  • I suspect you did something like delete that registry key in your setup project and then re-added it with the same name. That's the kind of thing that would make Visual Studio believe you're adding a new item to install, and that will give it a new internal component guid, and that will break the sharing. If you looked at both MSI files (old ad new) with Orca you's probably find in the Component table that the guid of the component containing that registry data is different.

    It basically works this way: Every file and registry item in your install has a guid. Upgrades work by installing all the new items onto the sysetm "on top of" the existing versions.  After the first install they all have a ref count of 1. After the upgrade, if all the component guids are the same then they all have a ref count of 2, and perhaps some binaries are new versions and replace the older versions.  The the old product is uninstalled, counting down all the ref counts. They should all decrement to 1 and leave everything behind. In your case this isn't happening, which is why it looks like guid was regenerated.


    Phil Wilson
    • Marked as answer by MattDendle Tuesday, September 28, 2010 8:00 AM
    Friday, September 24, 2010 7:59 PM
    Moderator

All replies

  • Hi Matt,

    The reason your upgrade is behaving this way has to do with component reference counting and product removal timing.

    You need to decide what type of upgrade you will be performing.  If you are always upgrading the same locations then the most efficient method is to have your all your MSI files share component guids for the same resources and adjust when you call RemoveExistingProducts action to after InstallFinalize.

    If you are changing folder locations and some registry values are shared between versions then you are likely going to want to uninstall the old product first and then install the new product.  In this case you don't need to worry about component guids (as much) and you can place RemoveExistingProducts action early in the Execute sequence (InstallValidate).

    Unfortunately I don't have VS2010 handy so I can't tell you what option to use to adjust this location of this action.  But you can always adjust the MSI itself through a post-build script. I suggest getting it working manually using the orca msi editor first.

    If you want to read up on what I am talking about-
    Component Reference Counting: http://robmensching.com/blog/posts/2003/10/18/Component-Rules-101 
    RemoveExistingProducts action: http://msdn.microsoft.com/en-us/library/aa371197(VS.85).aspx

    Sincerely,
    Adrian Accinelli

    • Marked as answer by MattDendle Tuesday, September 28, 2010 8:01 AM
    Friday, September 24, 2010 4:28 PM
  • I suspect you did something like delete that registry key in your setup project and then re-added it with the same name. That's the kind of thing that would make Visual Studio believe you're adding a new item to install, and that will give it a new internal component guid, and that will break the sharing. If you looked at both MSI files (old ad new) with Orca you's probably find in the Component table that the guid of the component containing that registry data is different.

    It basically works this way: Every file and registry item in your install has a guid. Upgrades work by installing all the new items onto the sysetm "on top of" the existing versions.  After the first install they all have a ref count of 1. After the upgrade, if all the component guids are the same then they all have a ref count of 2, and perhaps some binaries are new versions and replace the older versions.  The the old product is uninstalled, counting down all the ref counts. They should all decrement to 1 and leave everything behind. In your case this isn't happening, which is why it looks like guid was regenerated.


    Phil Wilson
    • Marked as answer by MattDendle Tuesday, September 28, 2010 8:00 AM
    Friday, September 24, 2010 7:59 PM
    Moderator
  • Thank you both for your replies.

    I have not knowly regenerated the componentIDs - I havent moved or re-added any keys, but I did change the RemoveAtUninstall property to true on the second MSI.  Would this re-generate the componentIDs?

    Thanks,

    Matt

    Monday, September 27, 2010 8:02 AM
  • Ive just loaded the MSIs into Orca, clicked on the Component table, and the ComponentIDs are the same

    The only difference is that there is an additional row (because i changed the install always property to true on a mid-level registry node). None of the existing records have a different componentID.

    I will see if I can extract the installer log when the updated MSI is installed - I recall seeing some reference counters in the verbose log.

    I will post back with the extra info.

     

    Cheers,

    Matt

     

    Monday, September 27, 2010 8:33 AM
  • I've trawled through the MSI log (Verbose plus extra bugging info) and there is no mention of reference counting on a per-component basis.

    Given that the componentIDs are the same, what could cause this behaviour?

    The only workaround I can see is if I set RemoveAtUninstall to false - but then if the user un-installs the item, the registry keys will never get removed.

    I am more than happy to post the MSI logs on here, but as ive used the full logging options, they're a bit lengthy!

    Kind Regards,

    Matt

    Monday, September 27, 2010 9:51 AM
  • Ive looked through the last 6 versions of the MSI that we have released.

    The very first version has completley different ComponentIDs - all subsequent versions have the same component IDs.

    So indeed Phil, you are correct in saying that the componentIDs have changed - but I have no idea why, nor why they have not changed in subsequent builds of the MSI.

    Can you tell me how Visual Studio 2010 persists the ComponentIDs between builds? I cannot see any reference to the component IDs in the VDPROJ file - however I can see the guids in the "Component" field of the "Component" table.  Does Visual Studio look at the previously built MSI and re-use the product codes in that? Or are they stored somewhere else?

    Thanks for your help both Adrian & Phil - its really been great.

    Matt

    Monday, September 27, 2010 11:40 AM
  • Visual Studio is a black box as far as generating compenent guids. I believe there's an internal algorithm, and I believe it's probably based on the location of the installed item on the target machine. I don't know what would change it, but I think that deleting something from the project and later adding it might cause a new guid to be generated, as I speculated before.
    Phil Wilson
    Monday, September 27, 2010 5:12 PM
    Moderator
  • Thanks again Phil and Adrian,

    Kind Regards,

    Matt Dendle

    Tuesday, September 28, 2010 8:01 AM