From MSI to WiX, Part 8 – Major Upgrade



  • The main page for the series is here.

 



Introduction


A typical Major Upgrade removes a previous version of an application and installs a new version.  This blog will guide you through the process of creating Major Upgrade.



Source code for RTM version


Let’s create a C# solution with two projects in it: library and console application.  Here is the code for the library:


using System;


using System.Collections.Generic;


using System.Text;


 


namespace TestLib


{


    public class TestClass


    {


        private string greeting;


 


        public TestClass()


        {


            greeting = “Hello, World!”;


        }


 


        public TestClass(string greeting)


        {


            this.greeting = greeting;


        }


 


        public void WriteLine()


        {


            Console.WriteLine(greeting);


        }


    }


}


Here is the code for the console application:


using System;


using System.Collections.Generic;


using System.Text;


using TestLib;


 


[assembly: AssemblyVersion(“1.0.0.0”)]


[assembly: AssemblyFileVersion(“1.0.0.0”)]


 


namespace TestApp


{


    class Program


    {


        static void Main(string[] args)


        {


            TestClass test = new TestClass();


            test.WriteLine();


        }


    }


}


As you can see, console application is using default constructor, so calling WriteLine method of the TestClass class will print out “Hello, World!” message.



Source code for V2 version


For version 2 of our product we will change the console application to use a non-default constructor to pass the greeting string the the TestClass instance:


using System;


using System.Collections.Generic;


using System.Text;


using TestLib;


 


[assembly: AssemblyVersion(“1.0.1.0”)]


[assembly: AssemblyFileVersion(“1.0.1.0”)]


 


namespace TestApp


{


    class Program


    {


        static void Main(string[] args)


        {


            TestClass test = new TestClass(“QFE version”);


            test.WriteLine();


        }


    }


}


Our updated version of application will print out “QFE version” message instead of default “Hello, World!”.  Notice also that AssemblyVersion and AssemblyFileversion have changed.



Installation Wix script with no Major Upgrade support


Typical installation script for such program would be something like this:


<?xml version=1.0 encoding=windows-1252?>


<Wix xmlns=http://schemas.microsoft.com/wix/2003/01/wi>


 


  <?define SkuName = “TestApp”?>


 


  <?define ProductVersion=”1.0.0″ ?>


  <?define UpgradeCode=”{3485E6A2-A1F3-4329-8BB5-ED8FFCF283D4}”?>


  <?define Manufacturer=”Acme Corp.”?>


  <?define ProductCode=”{5C32A3BD-3BA3-43AF-951F-1077E84B00DC}”?>


  <?define PackageCode=”{????????-????-????-????-????????????}”?>


 


  <Product Id=$(var.ProductCode)


           Name=ProductName


           Language=1033


           Version=$(var.ProductVersion)


           Codepage=1252


           Manufacturer=$(var.Manufacturer)


           UpgradeCode=$(var.UpgradeCode)>


 


    <Package Id=$(var.PackageCode)


             Description=PackageDescription


             Comments=Comments


             Manufacturer=$(var.Manufacturer)


             InstallerVersion=200


             Languages=1033


             SummaryCodepage=1252


             Compressed=yes


             AdminImage=no


             Platforms=Intel


             ReadOnly=yes


             ShortNames=no


             Keywords=Installer,MSI,Database />


 


    <Media Id=1 Cabinet=$(var.SkuName).cab EmbedCab=yes />


 


    <Directory Id=TARGETDIR Name=SourceDir>


      <Directory Id=LocalAppDataFolder>


        <Directory Id=INSTALLDIR Name=TestApp>


 


          <Component Id=$(var.SkuName) Guid={835A4136-B01E-4F8B-8EA7-5D6F69B07A83}>


            <File Id=TestAppExe DiskId=1 KeyPath=yes Checksum=yes


                  Vital=yesName=TestApp.exe Assembly=.net


                  AssemblyManifest=TestAppExe


                  AssemblyApplication=TestAppExe


                  Source=TestApp.exe />


          </Component>


 


          <Component Id=TestLibDll_Component Guid={5BC55186-170E-475C-B77A-D80581FC88EC}>


            <File Id=TestLibDll Name=TestLib.dll DiskId=1 KeyPath=yes


                  Vital=yes Assembly=.net AssemblyManifest=TestLibDll


                  AssemblyApplication=TestLibDll Source=TestLib.dll />


          </Component>


 


        </Directory>


      </Directory>


    </Directory>


 


    <Feature Id=Complete Level=1>


      <ComponentRef Id=$(var.SkuName) />


      <ComponentRef Id=TestLibDll_Component />


    </Feature>


 


  </Product>


</Wix>



Aside from UpgradeCode that script does not have any support for major upgrades.



Preparing an application for future major upgrades


Here is what needs to be done from purely MSI standpoint in order to support major upgrades:




  • Add a record to the Upgrade table to detect if installed on the system application has older version than current installation package.  We need this in case we need to apply conditions for upgrade only.  For example, we may update some configuration file during regular install and skip updating during upgrade thus preserving changes users might add to the configuration file after the original install.  This record should have the following values for columns:



    • UpgradeCode is set to the UpgradeCode property value



    • VersionMin is set to RTM version of the product



    • VersionMax is set to the current product version




    • Language can be set to a product language or empty




    • Attributes is set to msidbUpgradeAttributesVersionMinInclusive




    • Remove is empty





    • ActionProperty is set to the name of the public property which FindRelatedProducts action will set to the product code of already installed related product.  Suggested name for this property is UPGRADEFOUND.


  • Add a record to the Upgrade table to detect if current installation package contains an older version of an application.  We need this to prevent downgrading installed application to older version.  This record should have the following values for columns:



    • UpgradeCode is set to the UpgradeCode property value


    • VersionMin is set to current product version


    • VersionMax is empty


    • Language can be set to a product language or empty


    • Attributes is set to msidbUpgradeAttributesOnlyDetect


    • Remove is empty


    • ActionProperty is set to the name of the public property which FindRelatedProducts action will set to the product code of already installed related product.  Suggested name for this property is NEWPRODUCTFOUND.




  • Custom action Type 19 should be scheduled in both InstallExecuteSequence and InstallUISequence tables.  This action should be conditioned on NEWPRODUCTFOUND property.


  • MigrateFeatureStates action should be scheduled in both InstallExecuteSequence and InstallUISequence tables.  This action sets the feature states on installed application to reflect the feature states of already installed application.


  • RemoveExistingProducts action should be scheduled in InstallExecuteSequence table. This action removes the installed product or only updated files depending on where this action is scheduled in the InstallExecuteSequence table.


  • Both UPGRADEFOUND and NEWPRODUCTFOUND public properties  must be added to the SecureCustomProperties property.


  • Change ProductCode, PackageCode, and ProductVersion properties.


  • Important:  Product language defined in the Language attribute of <Product> element must be one of the languages listed in the Languages attribute of the <Package> element.

Here is how these items translates to Wix:




<Upgrade Id=$(var.UpgradeCode)>


  <UpgradeVersion Minimum=$(var.ProductVersion)


                  IncludeMinimum=no


                  OnlyDetect=yes


                  Language=1033


                  Property=NEWPRODUCTFOUND />


  <UpgradeVersion Minimum=$(var.RTMProductVersion)


                  IncludeMinimum=yes


                  Maximum=$(var.ProductVersion)


                  IncludeMaximum=no


                  Language=1033


                  Property=UPGRADEFOUND />


</Upgrade>



Id attribute of the <Upgrade> element is set to a value of UpgradeCode property (UpgradeCode attribute of <Product> element) and will be added to the UpgradeCode column of every record in the Upgrade table.


Every <UpgradeVersion> element adds a new record to the Upgrade table.


Minimum attribute of the <UpgradeVersion> element sets the value of VersionMin column.


Maximum attribute of the <UpgradeVersion> element sets the value of VersionMax column.


Property attribute of the <UpgradeVersion> element sets the value of ActionProperty column.


Here is the relationships between flag bits in Attributes column of the Upgrade table and attributes of the <UpgradeVersion> element:































Flag Attribute Description
msidbUpgradeAttributesMigrateFeatures MigrateFeatures Enables the logic of MigrateFeatureStates action of migrating feature states.
msidbUpgradeAttributesOnlyDetect OnlyDetect Detects products and applications but does not remove.
msidbUpgradeAttributesIgnoreRemoveFailure IgnoreremoveFailure Continues installation upon failure to remove a product or application.
msidbUpgradeAttributesVersionMinInclusive IncludeMinimum Detects the range of versions including the value in VersionMin.
msidbUpgradeAttributesVersionMaxInclusive IncludeMaximum Detects the range of versions including the value in VersionMax.
msidbUpgradeAttributesLanguagesExclusive ExcludeLanguages Detects all languages, excluding the languages listed in the Language column.



<!– Prevent downgrading –>


<CustomAction Id=PreventDowngrading


              Error=Newer version already installed. />




<InstallExecuteSequence>


  <Custom Action=PreventDowngrading


          After=FindRelatedProducts>NEWPRODUCTFOUND</Custom>


  <RemoveExistingProducts After=InstallFinalize />


</InstallExecuteSequence>


 


<InstallUISequence>


  <Custom Action=PreventDowngrading


          After=FindRelatedProducts>NEWPRODUCTFOUND</Custom>


</InstallUISequence>


Here is an updated installation script:


<?xml version=1.0 encoding=windows-1252?>


<Wix xmlns=http://schemas.microsoft.com/wix/2003/01/wi>


 


  <?define SkuName = “TestApp”?>



  <?define RTMProductVersion=”1.0.0″ ?>


  <?define ProductVersion=”2.0.0″ ?>


  <?define UpgradeCode=”{3485E6A2-A1F3-4329-8BB5-ED8FFCF283D4}”?>


  <?define Manufacturer=”Acme Corp.”?>


  <?define PackageCode=”{????????-????-????-????-????????????}”?>


 


  <Product Id={8EEB7D19-F7F4-4218-93B9-BBEAAA4C2E2D}


           Name=ProductName


           Language=1033


           Version=$(var.ProductVersion)


           Codepage=1252


           Manufacturer=$(var.Manufacturer)


           UpgradeCode=$(var.UpgradeCode)>


 


    <Package Id=$(var.PackageCode)


             Description=PackageDescription


             Comments=Comments


             Manufacturer=$(var.Manufacturer)


             InstallerVersion=200


             Languages=1033


             SummaryCodepage=1252


             Compressed=yes


             AdminImage=no


             Platforms=Intel


             ReadOnly=yes


             ShortNames=no


             Keywords=Installer,MSI,Database />


 


    <Media Id=1 Cabinet=$(var.SkuName).cab EmbedCab=yes />


 


    <Upgrade Id=$(var.UpgradeCode)>


      <UpgradeVersion Minimum=$(var.ProductVersion)


                      IncludeMinimum=no


                      OnlyDetect=yes


                      Language=1033


                      Property=NEWPRODUCTFOUND />


      <UpgradeVersion Minimum=$(var.RTMProductVersion)


                      IncludeMinimum=yes


                      Maximum=$(var.ProductVersion)


                      IncludeMaximum=no


                      Language=1033


                      Property=UPGRADEFOUND />


    </Upgrade>


 


    <Directory Id=TARGETDIR Name=SourceDir>


      <Directory Id=LocalAppDataFolder>


        <Directory Id=INSTALLDIR Name=TestApp>


 


          <Component Id=$(var.SkuName) Guid={835A4136-B01E-4F8B-8EA7-5D6F69B07A83}>


            <File Id=TestAppExe DiskId=1 KeyPath=yes Checksum=yes


                  Vital=yesName=TestApp.exe Assembly=.net


                  AssemblyManifest=TestAppExe


                  AssemblyApplication=TestAppExe


                  Source=TestApp.exe />


          </Component>


 


          <Component Id=TestLibDll_Component Guid={5BC55186-170E-475C-B77A-D80581FC88EC}>


            <File Id=TestLibDll Name=TestLib.dll DiskId=1 KeyPath=yes


                  Vital=yes Assembly=.net AssemblyManifest=TestLibDll


                  AssemblyApplication=TestLibDll Source=TestLib.dll />


          </Component>


 


        </Directory>


      </Directory>


    </Directory>


 


    <Feature Id=Complete Level=1>


      <ComponentRef Id=$(var.SkuName) />


      <ComponentRef Id=TestLibDll_Component />


    </Feature>


 



    <!– Prevent downgrading –>


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


 


    <!– Sequences –>


    <InstallExecuteSequence>


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


      <RemoveExistingProducts After=InstallFinalize />


    </InstallExecuteSequence>


   


    <InstallUISequence>


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


    </InstallUISequence>


  </Product>


</Wix>



How upgrade works




  • The FindRelatedProducts action runs through each record of the Upgrade table in sequence and compares the upgrade code, product version, and language in each row to products installed on the system. When FindRelatedProducts detects a correspondence between the upgrade information and an installed product, it appends the product code to the property specified in the ActionProperty column of the Upgrade table (Property attribute of the <UpgradeVersion> element).


For FindRelatedProducts to work correctly, the package author must be sure that the ProductLanguage property in the Property table is set to a language that is also listed in the Template Summary Property.


FindRelatedProducts should be authored into the InstallUISequence table and InstallExecuteSequence tables.  The FindRelatedProducts action must come before the MigrateFeatureStates action and the RemoveExistingProducts action.




  • MigrateFeatureStates reads the feature states in the existing application and then sets these feature states in the pending installation. The method is only useful when the new feature tree has not greatly changed from the original.


MigrateFeatureStates action runs through each record of the Upgrade table in sequence and compares the upgrade code, product version, and language in each row to all products installed on the system. If MigrateFeatureStates action detects a correspondence, and if the msidbUpgradeAttributesMigrateFeatures bit flag is set in the Attributes column of the Upgrade table, the installer queries the existing feature states for the product and sets these states for the same features in the new application. The action only migrates the feature states if the Preselected property is not set.


The MigrateFeatureStates action should come immediately after the CostFinalize action. MigrateFeatureStates must be sequenced in both the InstallUISequence table and the InstallExecuteSequence table.



  • The RemoveExistingProducts action goes through the product codes listed in the ActionProperty column of the Upgrade table and removes the products in sequence by invoking concurrent installations. For each concurrent installation the installer sets the ProductCode property to the product code and sets the REMOVE property to the value in the Remove field of the Upgrade table. If the Remove field is blank, its value defaults to ALL and the installer removes the entire product.


The RemoveExistingProducts action must be scheduled in the action sequence in one of the following locations.




    • Between the InstallValidate action and the InstallInitialize action. In this case, the installer removes the old applications entirely before installing the new applications. This is an inefficient placement for the action because all reused files have to be recopied.
    • After the InstallInitialize action and before any actions that generate execution script.
    • Between the InstallExecute action, or the InstallExecuteAgain action, and the InstallFinalize action. Generally the last three actions are scheduled right after one another: InstallExecute, RemoveExistingProducts, and InstallFinalize. In this case the updated files are installed first and then the old files are removed. However, if the removal of the old application fails, then the installer rolls back both the removal of the old application and the install of the new application.
    • After the InstallFinalize action. This is the most efficient placement for the action. In this case, the installer updates files before removing the old applications. Only the files being updated get installed during the installation. If the removal of the old application fails, then the installer only rolls back the uninstallation of the old application.

Windows Installer sets the UPGRADINGPRODUCTCODE Property when it runs this action.


 

Comments (44)

  1. Ramon says:

    Hello, I have a question.

    Suppose that version 1 of your  application (Wix script with no Major Upgrade support) is installed on a system, is it possible to update it with version 2 or a similar implementation without having to manually uninstall first?

    Thanks!

  2. greg says:

    That’s a really good post Alex. I’ve used your content to add a major install to my language pack and i’m not sure i could have done it without you page to reference/copy.

    Thanks for the effort.

    Greg.

  3. lupetti says:

    Great post Alex. I successfully used your code for implementing a major upgrade.

    It all worked fine until I had to change my product name.

    Since my product name has changed, it seems that FindRelatedProducts does not find the older version, and after performing the upgrade I find 2 entries in add/remove programs (the old and new name). Do you possibly know how to solve this issue?

  4. NDJ says:

    Thank you so much for this brilliant post, you can’t imagine how much time I was losing trying to get an upgrade to work!  

  5. Logan says:

    Just a note to warn others: if the version number is supplied as four components (x.x.x.x), the fourth component will be IGNORED. Therefore, in order for a version to be considered new by Windows Installer, at least one of the initial three components must change. I burned a whole day on this one. 😛

  6. Logan says:

    @lupetti: Make sure the UpgradeCode is the same for both the old and new version (in the Upgrade table) and (as I just posted), the change in version number is one of the first three components of the version. Also make sure you haven’t changed the per-machine/per-user setting as this can throw things off as well.

  7. Sol Young says:

    I’m with Ramon – If an UpgradeCode wasn’t included in version 1, will an upgrade easily be detected for a version 2 that includes an UpgradeCode? Or is there additional code to write?

    Your site is a fantastic resource btw!

  8. Dave says:

    I’m also in with Ramon’s question. I need always perform an auto uninstall of a previous version whether its major or monor.

    Any suggestions Alex?

  9. Alex Shevchuk says:

    Regarding Ramon’s question on missing UpgradeCode in Version 1.  Unfortunately, I don’t think anything can be done to allow automatic major upgrade.

    To enable major upgrade Windows Installer requires UpgradeCode, ProductVersion and ProductLanguage properties identified in the installation package.  That is why the Best Practice with any installation package is to always assign values for these properties.

  10. Prabhakaran says:

    I followed the same steps as indicated above and i have created an updated MSI package to update the program and also the script in the database, but when i install the updated MSI package the SQL statements are not updated in the database

    An ideas?

  11. Alex Shevchuk says:

    Hi Prabhakaran,

    Without knowing specifics it is hard to say why SQL statements are not updated. It could be an issue with when RemoveExistingProducts is scheduled to run (keypath for component is the same if REP is scheduled too late) or problem could be in the way how you install SQL statements.

    Alex

  12. Prabhakaran says:

    Hi Alex,

    Thanks for the prompt reply. I have fixed the database update issue which i mentioned earlier. Now i have got a new issue i have 2 MSI packages, Error MSI and Fixed MSI. I would upgrade my Setup package using the Fixed MSI but again if i run the Error MSI the Setup package turns back again to the older version.

    Is there anything to stop this or any suggestions?

  13. Alex Shevchuk says:

    Hi Prabhakaran,

    If I understood you correctly, you are having downgrading issue.  Search for "PreventDowngrading" in the post above.

  14. Prabhakaran says:

    Hi Alex,

    You are right i am having the downgrading issue i am using the same steps as mentioned above but it still downgrades.

    I am using the following line to start the updated MSI package

    msiexec /i Fixed.msi REINSTALL=ALL REINSTALLMODE=vomus

    Am i right or going wrong somewhere i dont know where it is. If needed i can post you both the source files.

  15. Alex Shevchuk says:

    This command is for minor updates. To apply major upgrade simply install new msi:

    msiexec /i Fixed.msi

  16. Anup says:

    Hello

    I followed your blog and I am able to sucessfully upgrade with the new MSI. ( major upgrade). Now when I use the new msi to uninstall the product, it fails with error ( this action is only valid for currently installed products.)

    Can you provide some insights on what could be done to fix this ?

  17. Alex Shevchuk says:

    Make sure that new version has both Product and Package codes different from original package.

  18. peter cli says:

    How to prevent  a custom action from running during a upgrade ?

    i have this :

           <Custom Action=’CreateScheduledTask’ After=’InstallFinalize’>NOT Installed</Custom>

    But this runs during the upgrade.

    Thanks,Peter

  19. Alex Shevchuk says:

    Hi Peter,

    During upgrade Windows Installer sets the UPGRADINGPRODUCTCODE property.  You can use it in conditions.

  20. Abhishek says:

    Hello Alex,

    I used created a wix based on the example given above.

    The first time I installed the msi, it works great. There were no installations problems.

    I created a new build and installed the msi

    I get this error

    [Window Title]

    Windows Installer

    [Main Instruction]

    Another version of this product is already installed.  Installation of this version cannot continue.  To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel.

    [OK]

    Can you please help me in finding the solution to this problem.

    This is the behaviour I am expecting. When I install a new build, it should Uninstall the old version and install the new one.

  21. Alex Shevchuk says:

    Hi Abhishek,

    Make sure you change Product Code (Product/@Id), Package Code (Package/@Id), and Product Version (Product/@Version). During upgrade only first three fields of Product Version are recognized. Fourth field is ignored and if two versions are different in fourth field only, they will be considered as the same version by Windows Installer.

    Also, make sure that Upgrade/@Id has the same value as Product/@UpgradeCode and UpgradeVersion elements have correct values for Minimum and Maximum attributes.

  22. Abhishek says:

    Thank you very much for the quick response.

    I generate a new guid for the Package.

    I dont generate a new guid for the Product.

    I have been testing with desktop builds.

    So the version of the product was not changing. I will change the Product version and try this. Will give an update after I try this.

    Do you want me to generate the Product guids too? When I did this installations happens succesfully but the the uninstall did not happen.

  23. Amy Rosewater says:

    I have a major upgrade authored into my wxs file as well.  When I attempt to run the upgrade, I get a message in the verbose log from the RemoveExistingProducts action that states "Ignoring failure to remove product during upgrade – product already uninstalled."  The product is definitely not already uninstalled, and then end result is the upgrade occurs, but now there are 2 instances of the product in ARP.  Is there something I am doing wrong?

  24. Abhishek says:

    1. My wix project is for a Visual studio package application. I generated a wix using the sample above.

    1. When I install the msi for the first time, it installs successfully. I see the msi in Program and features with the right version.

    2. I generate a new build and then install the msi again. The new version gets successfully installed. I see the new version in Program and features. But when I look at the dlls installed. They have not been refreshed yet. They are still from the previous build. The upgrade did not refresh the dlls. Any help on this would be great.

  25. Abhishek says:

    Please ignore my previous question. I got it working. I followed the instructions here and it worked.

    Thank you very much Alex. This blog is excellent.

  26. Rado G says:

     Alex, thank for the great post.

     We had per user installation, but we had to make it per machine or per user.

     My initial approach was to use HKMU key and change "ALLUSERS" property in the custom build step if the user is privileged, but that broke full upgrade.

     I fixed the problem by separating per user and per machine registry keys and changing the installation path if the user is not privileged.  

     And you post convinced me that  this is the right solution in our case.

  27. BarryH says:

    Mr Shevchuk,

    Excellent work.  Bare with my ignorance; I hope you can steer me in the right direction.

    For the next release of my product, and for the first time, we will use WiX, instead of InstallShield.  The release cycle is longish and we will have to generate a number of Alpha/Beta/RC builds for internal testing. My questions:

    1) What is your recommended approach to upgrading these internal, pre-release, versions? A “Major Upgrade” seems a tad heavy handing since we’d have to change the ProductCode etc for every build and this could lead to, if I understand it correctly, an accumulation of said “codes”.  I should mention that completely uninstalling  the product before installing the new version is not an issue.  I’m looking for the most straightforward means of doing this.

    2) What is your recommended approach to upgrading from a previous RTM version that used InstallShield which, as I understand it, does not result in having a handy UpgradeCode?

    Many Thanks (even if you choose NOT to answer)

  28. Alex Shevchuk says:

    Major upgrade is by far the easiest of upgrades/updates. It is even more so for pre-release development because it allows changing feature tree layout (move or delete feature, add subfeature), move or delete components, change the component code of existing component, change keypath of the component, etc. As far as major upgrade implementation, all it needs is upgrade code and version min/max. You still will need to keep track of product codes in some cases.  For example, installation is done by using bootstrapper and you want to have some extra processing based on which version is being updated.

    I don’t have lot of experience with InstallShield, but I’ll be surprised if their MSI’s don’t have UpgradeCode.  For first WiX-based version of installer which upgrades InstallShield installer, you may want to schedule RemoveExistingProducts earlier, preferably between InstallValidate and InstallInitialize.

  29. BarryH says:

    Many thanks for your excellent feedback and recommendations. I was secretly hoping you would suggest the major upgrade route; it looks like the most straightforward, definitive and flexible way to go.

    (Ever thought about authoring a book on the subject?)

  30. Harald Gröne says:

    Thank you so much, Alex.

    My Upgrades stopped working, when I introduced languages. Finally I found the solution in your blog.

    I had to add Language = ‘1031’ in <Upgrade Version>.

    This Blog is great.

  31. Pramod says:

    Alex,

    Thx for great post.

    I want to updrade the previous version of the product with the new one. The code is working fine if the upgradecode of both versions is same. But I want the new version with different upgradeCode. So how can I upgrade a previous version with different upgrade code?

  32. whgibbo says:

    Hi Alex,

    Great example, has helped me a lot.  But I do have a problem, was wondering if you could help.

    — Start of Product.wxs —

    <?xml version="1.0" encoding="UTF-8"?>

    <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"&gt;

    <Product Id="48C49ACE-90CF-4161-9C6E-9162115A54DD"

    Name="WiX Patch Example Product"

    Language="1033"

    Version="1.0.1"

    Manufacturer="Dynamo Corporation"

    UpgradeCode="48C49ACE-90CF-4161-9C6E-9162115A54DD">

    <Package Compressed="yes"

    Description="Installs a file that will be patched."

    Comments="This Product does not install any executables"

    InstallerVersion="200"

    InstallScope="perMachine"

    />

    <Media Id="1" Cabinet="product.cab" EmbedCab="yes" />

    <FeatureRef Id="SampleProductFeature"/>

    </Product>

    <Fragment>

    <Feature Id="SampleProductFeature" Title="Sample Product Feature" Level="1">

    <ComponentRef Id="SampleComponent" />

    <ComponentRef Id="Sample2" />

    </Feature>

    </Fragment>

    <Fragment>

    <DirectoryRef Id="SampleProductFolder">

    <Component Id="SampleComponent" Guid="{C28843DA-EF08-41CC-BA75-D2B99D8A1983}" DiskId="1">

    <File Id="SampleFile" Name="Sample.txt" Source="$(var.ProjectDir)..FilesPatch1Readme.txt"/>

    </Component>

    <Component Id="Sample2" Guid="{923248E0-B4B5-4c8c-B343-420EE64CEF88}" DiskId="1">

    <File Id="SampleFile2" Name="Sample2.txt" Source="$(var.ProjectDir)..FilesPatch1Readme2.txt" />

    </Component>

    </DirectoryRef>

    </Fragment>

    <Fragment>

    <Directory Id="TARGETDIR" Name="SourceDir">

    <Directory Id="ProgramFilesFolder" Name="PFiles">

    <Directory Id="SampleProductFolder" Name="Patch Sample Directory">

    </Directory>

    </Directory>

    </Directory>

    </Fragment>

    </Wix>

    — End of Product.wxs —

    — Start of Patch.wxs —

    <?xml version="1.0" encoding="UTF-8"?>

    <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"&gt;

       <Patch

           AllowRemoval="yes"

           Manufacturer="Dynamo Corp"

           MoreInfoURL="http://www.dynamocorp.com/&quot;

           DisplayName="Sample Patch"

           Description="Small Update Patch"

           Classification="Update"

    OptimizedInstallMode="yes"

           >

           <Media Id="5000" Cabinet="RTM.cab">

               <PatchBaseline Id="RTM"/>

           </Media>

           <PatchFamily Id=’SamplePatchFamily’

    ProductCode="48C49ACE-90CF-4161-9C6E-9162115A54DD"

    Version=’1.0.1′

    Supersede=’no’>

               <ComponentRef Id="SampleComponent"/>

           </PatchFamily>

       </Patch>

    </Wix>

    — End of Patch.wxs —

    And followed you instructions, it created a patch.  But rather than updating just the individual component, it updates all components 🙁

    Any ideas ?

  33. rkhj says:

    Thanks for the great blog Alex!

    I’m having a problem though with the Windows caching of the installer. I’m trying to do an upgrade and each time the Windows installer is launching the installer of the older version. And when I do the upgrade it is complaining about problems with reading the older version’s msi file (because its not in the same directory anymore).

    I did change the UpgradeCode but kept the Product and Package codes the same. I also have different ProductVersion codes (2.2.3 vs 2.3.0).

    Thanks,

  34. Cody says:

    Hi Alex, I have two questions for you if you please.

    1. As far as we need a RemoveExistingProducts action only when we install product, don't we need some condition on it? Like "NOT REMOVE=ALL" or something like this?

    2. You say that location of RemoveExistingProducts action before InstallInitialize action is inefficient and that most efficient placement for this action is after InstallFinalize action. Right? But where I must to place it if some action which deals with uninstallation(I placed them before the UnpublishComponents action)  removes files, stops service, etc. I am afraid if I place RemoveExistingProducts after InstallFinalize there will be some comflicts. Can you suggest me something?

  35. Alex Shevchuk says:

    Hi Cody,

    For your first question – quote from
    msdn.microsoft.com/…/aa371197(VS.85).aspx:

    "The installer only runs the RemoveExistingProducts action the first time it installs a product. It does not run the action during a maintenance installation or uninstallation."

    So, the answer is: there is no need to do any additional scheduling, MSI will take care of it.

    As far as scheduling, it is very tricky.  Even though scheduling REP after InstallFinalize is the most efficient, it may not always possible to schedule REP at this point.  Sometimes you have to schedule it before InstallInitialize if there are special CA’s
    on uninstall.  Also, keep in mind that when REP uninstalls the old product, it sets UPGRADINGPRODUCTCODE property which you can use to schedule CA to run only during uninstall or during old product uninstall.  This may help you in scheduling REP after InstallFinalize
    by splitting your CA to two separate: one for product uninstall and another one for old product uninstall during upgrade.

    Hope this helps,

    Alex

  36. Cody says:

    Alex, thanks for your reply, its realy helpful. I was wery inattentive reading this msdn article before. Also I know about UPGRADINGPRODUCTCODE property and I using it. My question was more like curiosity: I thought may be there is some little-known mechanism for such situations… well.. looks like not.

    Any way thanks for you help.

  37. Andrey says:

    Добрый день. Я слаб в английском, и чтоб лучше объснить суть проблем пишу на русском)

    Повторяю в точность все выше описанные шаги, но мой installer  ни как не хочет обновлять предыдущею версию программы. Шаги:

    1. Собрал приложение в студии. Запускаю мой installer.

    2. Все прекрасно устанавливается.

    3. Повторно запускаю installer, мне предлагается выбрать вариант установки, Изменить, Восстановить, или Удалить. Тут все ок!

    4. Если ЗАНОВО сдлеать Rebuild solution в студии(при этом НИ строчки кода НЕ менялось!!!). И снова запустить installer, то сразу же появляется окно, мол: Есть старая версия удали ее сначала плиз! 🙁

    Another version of this product is already installed. Installation of this version cannot continue.

    To configure or remove the existing version of this product, use Add/Remove Programs on the Control Panel.

    Вот мой код:

    <?xml version="1.0" encoding="UTF-8"?>

    <Wix xmlns="schemas.microsoft.com/…/wi">

    <?define SkuName = "TestApp"?>

    <?define RTMProductVersion="1.0.0" ?>

    <?define ProductName="SetupProject1" ?>

    <?define ProductVersion="2.0.0.0" ?>

    <?define ProductCode="b7bc7c6f-9a4e-4973-be84-eca8e3427c97"?>

    <?define UpgradeCode="06a81104-1e30-463d-87e1-e8a79b4c682a"?>

    <?define PackageCode="{8EB1B635-E70B-4F5D-B1CE-C2B25E63A3F5}"?>

    <?define Manufacturer="MyCompany"?>

    <Product Id="$(var.ProductCode)" Name="$(var.ProductName)" Language="1049" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">

    <Package Id="$(var.PackageCode)" Manufacturer="$(var.Manufacturer)"

    InstallerVersion="200"

    SummaryCodepage='1252'

                Compressed='yes'

                AdminImage='no'

                Platforms='Intel'

                ReadOnly='yes'

                ShortNames='no'

                Keywords='Installer,MSI,Database'

    />

    <Media Id="1" Cabinet="$(var.SkuName).cab" EmbedCab="yes" />

    <Upgrade Id="$(var.UpgradeCode)">

    <UpgradeVersion Minimum="$(var.ProductVersion)"

    IncludeMinimum="no"

    OnlyDetect="yes"

    Language="1033"

    Property="NEWPRODUCTFOUND" />

    <UpgradeVersion Minimum="$(var.RTMProductVersion)"

    IncludeMinimum="yes"

    Maximum="$(var.ProductVersion)"

    IncludeMaximum="no"

    Language="1033"

    Property="UPGRADEFOUND"/>

    </Upgrade>

    <Directory Id="TARGETDIR" Name="SourceDir">

    <Directory Id="ProgramFilesFolder">

    <Directory Id="INSTALLLOCATION" Name="$(var.ProductName)">

    <Component Id="ProductComponent" Guid="b11556a2-e066-4393-af5c-9c9210187eb2">

    <File Id='Calc' DiskId='1' Source='C:WINDOWSsystem32calc.exe'/>

    </Component>

    </Directory>

    </Directory>

    <Directory Id="ProgramMenuFolder">

    &

  38. Willy G says:

    Hi Alex (or anyone that can help),

      I have inserted this code into two various builds now and both still do not upgrade automatically. It throws me a message that "Another version of this product is already installed. Installation of this version cannot continue. To configure or remove…"

      Can someone point me into the right direction as to what I may be missing? Thanks in advance.

  39. kit says:

    I have the same problem 🙁

  40. DaveC4 says:

    I've run into an interesting issue with trying to schedule REP at the end of the install. Everything works fine (as expected) when a component is being upgraded (or downgraded) in the new installer. However, if the component is unchanged, while the end result is correct (file not copied, ref count is good [during REP, the action state is the expected 'null']), the action state of the component implies the file is being installed. This means the CAs associated with the component actually get run. This is bad. (We're trying to minimize driver churn and reboots)

    Is there any way to condition a CA on the true state? So far my investigation seems to indicate there isn't since the determination to not copy the file isn't actually made until the InstallFiles action in the deferred sequence.

  41. SCCM says:

    I've been built same code with two different version numbers. Installed the first MSI and tried to use the second to uninstall (I was hoping that would work as the upgrade code is the same); however, I get "Another version of this product is already installed" message.

    Plz help……

  42. SCCM says:

    I've have built same code with two different version numbers. Installed the first MSI and tried to use the second to uninstall (I was hoping that would work as the upgrade code is the same); however, I get "Another version of this product is already installed" message.

    Plz help……

  43. anu.deep@live.com says:

    Hi Alex,

    I am facing now a days problem with upgrade. I made a Web Application upgrade with proper rules of upgrade but it is not copying files from source directory. It will make double entry in 'Program and features'.  and not upgrade the previous version. I made everything proper as I seen. I checked UpgradeVersion, AdminUISequence, InstallUISequence, InstallExecuteSequence. Everything in a right manner. It is not working. Whats the problem? Whats I am missing?

  44. Sonal Jain says:

    Thank you so much for this. I was struggling for a long time.