0

I would like to know if there is any way I can overwrite the old files using a newer version of the product. There are a few hundred files, so is there a better way to do this? As the upgrade is completely wiping out all files. I would like the upgrade MSI to overwrite the files.

My upgrade logic is as follows:

<Upgrade Id="$(var.UpgradeCode)">
      <UpgradeVersion Minimum="$(var.ProductVersion)"
                      IncludeMinimum="no"
                      OnlyDetect="yes"                        
                      Property="NEWPRODUCTFOUND" />
      <UpgradeVersion Minimum="$(var.RTMProductVersion)"
                      IncludeMinimum="yes"
                      Maximum="$(var.ProductVersion)"
                      IncludeMaximum="no"                         
                      Property="UPGRADEFOUND" />
</Upgrade>

<CustomAction Id="PreventDowngrading" Error="Newer version already installed" />

<InstallUISequence>
  <Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>
</InstallUISequence>

<InstallExecuteSequence>
  <Custom Action="PreventDowngrading" After="FindRelatedProducts">NEWPRODUCTFOUND</Custom>
  <RemoveExistingProducts After="InstallFinalize" />      
  <InstallExecute After="RemoveExistingProducts"  />
</InstallExecuteSequence>
varun7447
  • 574
  • 1
  • 6
  • 27
  • A major upgrade will do that, but you have not provided enough info, and not described what's happening. The upgrade requires same UpgradeCode, new ProductCode and PackageCode, incremented ProductVersion in the first 3 fields, and file versions incremented for those you wish updated. – PhilDW Jul 21 '17 at 17:10
  • upgrade completely uninstalled all the files and install only few of the files. I have the same UpgradeCode, For productCode i am using *, Package code ``. I have also incremented product version from 1.0.0 to 1.0.1. – varun7447 Jul 21 '17 at 17:32
  • 1
    Just to state the obvious, that upgrade you're doing is NOT a "patch", it's required to be a complete product install that will install fresh for new users. It must have all the files in it. If you want a package that updates only some files then build a patch package, a .msp file. – PhilDW Jul 21 '17 at 17:50
  • So I have created the patch file based of two releases. The second one has lot of updated files. Now when I run the pyro command , I get an exception about there is no different transform file. Is this possible? Is the patch file created based on the time stamp of the files or file size of the files or only when there are new files added to the new version? – varun7447 Jul 22 '17 at 04:31
  • Here is the error message.. error PYRO0227 : The transform being built did not contain any differences so it could not be created – varun7447 Jul 22 '17 at 05:07
  • _upgrade is completely wiping out all files_ ... If you place `RemoveExistingProducts` after `InstallFinalize` you have to make sure to strictly follow component rules. For one, component GUIDs must be stable between different versions of the package, else reference counting will not work and files might be removed as you noticed. To always follow component rules can be hard, especially with complex packages so I suggest placing `RemoveExistingProducts` between the `InstallValidate` action and the `InstallInitialize` action. It is less efficient but much more reliable. – zett42 Jul 22 '17 at 11:56
  • I tried both, still has the same problem. I guess I should create patch using pyro but I am getting above exception that the "transform being built does not contain any differences so it could not be created.." – varun7447 Jul 22 '17 at 18:39
  • having issues with the patch. Patch is not replacing the changed files with the latest files. generated the componentref using harvest , this will auto generate guid every build, does this matter. The number of files changed in the latest MSI are lot it is hard to keep track of them. Also I have not updated the assemblyversion.cs file after the first release, does this matter? Installer is a web application, it has a combination of DLL and JS files. Not sure how to track the JS files with file version. – varun7447 Jul 27 '17 at 02:05

1 Answers1

2

I will need to write this quickly, please bear with me, but here goes:

Component GUIDs must stay the same between packages for files to update correctly, especially when you deploy via a patch. The key symptom of mismatching component GUIDs is exactly missing files after the deployment is complete (and patches that never work).

Set up a proper major upgrade as explained by PhilDW, and keep the component GUIDs consistent between releases and follow the component creation rules, and your upgrade should work correctly (and your patches too).

Note that you can leave the component GUIDs out of the WiX source file and allow them to be auto-generated rather than hard coded, and you will still get consistent GUIDs. Auto-generation of GUIDs will calculate a stable GUID (please read the linked question, the accepted answer along with all its comments) that remains stable between releases unless you rename or move the file in question - this requires a new component GUID, and here is why (this also explains why auto-generating stable GUIDs is possible). Auto-GUID generation will detect when a new GUID is required.

I am not up to speed on harvesting via heat.exe, but I think it allows the component GUIDs to be auto-generated rather than hard coded. Just change your script or automation process to set component GUIDs to auto-generate (this uses a * instead of a GUID in the component tag). Please read this entire answer with all answers and comments as well: Syntax for guids in WIX?

Important! A patch is just a delivery method for an MSI upgrade that is already working as a full package. Don't waste any time generating patches until you have verified that the full, updated MSI package upgrades the previous version correctly. You will just waste time if you do - the patch will never work if the full update doesn't work. It can't.

Is the first version of your product live? If it is not I would suggest starting over from scratch and use auto-generated GUIDs. If your previous version is live and you have hard coded component GUIDs you either need to match the existing component GUIDs in your first version with the component GUIDs in the updated version, OR you must put RemoveExistingProducts early in the InstallExecuteSequence as suggested by zett42 to allow the old version to fully uninstall before the new version is installed. This will prevent the previous error in component referencing to affect the major upgrade and no files should be missing after the upgrade. Patching will not be possible in this approach at all since component referencing isn't correct. This makes both minor and major upgrade patching fail - both require 100% component referencing to work properly.

This has already become long. If this all sounds Greek to you, please read up on the linked stackoverflow answers and get your head around MSI component creation best practice and component referencing in general. See MSDN as well for this. I will check back and see how you get on, and perhaps clean up this answer a little bit once I know what isn't clear and where you are at.

Stein Åsmul
  • 39,960
  • 25
  • 91
  • 164
  • I do have the first version of the product live. I have been using heat to generate Compnent GUID usin -gg option. But I have not used the option -ag (Auto generate component guids at compile time, e.g. set Guid="*".). The idea of InstallExecuteSequence to remove the existing product is something that i wanted to avoid. Option of -aa in heat will throw exceptions like how it is stated here https://stackoverflow.com/questions/24665555/wix-how-to-allow-autogenerated-componentgroup-to-autogenerate-guids if the installation of product is different from ProgramFilesFolder. – varun7447 Aug 01 '17 at 01:11
  • Do you have the wxs file for your live release? You can manually update this file with added / deleted files and hence preserve the component GUIDs between releases. This will no doubt take some time, but I don't see any other options unless you go down the "uninstall existing product completely first" path (putting RemoveExistingProduct early in the InstallExecuteSequence). The good news is that if you follow component rules this manual way, you might be able to get your patch working as well, though major upgrade patches are not recommended. – Stein Åsmul Aug 01 '17 at 01:22
  • Can I ask where you are installing files outside of the ProgramFilesFolder hierarchy btw? There are valid cases to do so, but more often than not this is a "deployment smell". There are more and more obstacles in place for deployment on Windows - going vanilla will often save you a lot of work. In many cases minor changes to your application's design can lead to huge improvement for deployment (avoiding undesirable deployment designs). – Stein Åsmul Aug 01 '17 at 01:26
  • I generate the was file on the fly as it has not few files but hundreds of files. .wxs file is generated using heat.exe. yeah i will try the uninstall existing products as the last option when i don't have any other options left. I am creating the installer for a webapplication hosted on IIS. The reason for not installing the product to ProgramFilesFolder is permissions. Also some users might not have access to install the product to ProgramFilesFolder. – varun7447 Aug 01 '17 at 01:32
  • Yes, IIS deployment would be a good reason to go outside ProgramFilesFolder. I guess you are out of options apart from "uninstall early and completely" then? – Stein Åsmul Aug 01 '17 at 01:35
  • Yes so you are suggesting to remove the existing product and do the major upgrade? I see there is no other option at this point. – varun7447 Aug 01 '17 at 01:45
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/150667/discussion-between-stein-asmul-and-varun7447). – Stein Åsmul Aug 01 '17 at 01:46