[wix-users] FW: Advice on an upgrade [P]

Steven Ogilvie Steven.Ogilvie at titus.com
Wed Nov 25 15:57:57 PST 2015


Classification: Public
Any help would be appreciated!

I have the temporary record working, BUT I am not sure why it is not being kicked off (upgradecode to remove an old MSI that is not in an upgrade package)

<!-- Remove Core Plug-ins on upgrade -->
      <Custom Action="CA_Set_RemovePluginsOnUpgrade" Before="InstallValidate">WIX_UPGRADE_DETECTED</Custom>
      <Custom Action="CA_REMOVEPLUGINS_ONUPGRADE" After="CA_Set_RemovePluginsOnUpgrade">WIX_UPGRADE_DETECTED</Custom>
    </InstallExecuteSequence>

<CustomAction Id="CA_Set_RemovePluginsOnUpgrade" Property="CA_REMOVEPLUGINS_ONUPGRADE" Value="[ADMIN_GUID]|[CLIENT_GUID]|[CLIENT_MSI_GUID]|[PLUGIN_GUID]" HideTarget="yes"/>
    <CustomAction Id="CA_REMOVEPLUGINS_ONUPGRADE" BinaryKey="BIN_CustomAction" DllEntry="RemovePluginsOnUpgrade" Impersonate="yes" Execute="immediate" Return="asyncWait"/>

Custom Action:
[CustomAction]
        public static ActionResult RemovePluginsOnUpgrade(Session session)
        {
            try
            {
                if (session == null)
                {
                    throw new ArgumentNullException("session");
                }

                var db = session.Database;
                var upgradeView = db.OpenView("SELECT * FROM Upgrade");
                upgradeView.Execute();

                var info = session.Database.Tables["Upgrade"];
                Record record = session.Database.CreateRecord(info.Columns.Count);
                record.FormatString = info.Columns.FormatString;
                record.SetString(1, "{<upgrade code>}");  // UpgradeCode
                record.SetString(2, "15.4.10.19");                              // VersionMin
                record.SetString(3, "15.4.10.19");                              // VersionMax
                record.SetString(4, "");                                        // Language
                record.SetInteger(5, 0x00000300);                               // Attributes
                record.SetString(6, "");                                        // Remove
                record.SetString(7, "REMOVEPLUGINS");                           // ActionProperty

                WriteInfoLogInstall(session, "record is: " + record, true);

                upgradeView.InsertTemporary(record);            //InsertTemporary
                upgradeView.Close();

                WriteInfoLogInstall(session, "upgradeview close", true);
                
            }
            catch (Exception ex)
            {
                WriteErrorLogInstall(session, "RemovePluginsOnUpgrade failed: ", ex, true);
                return ActionResult.Failure;
            }

            WriteSuccessLogInstall(session, "RemovePluginsOnUpgrade: The removal of the old Core Plug-ins from the system succeeded.", true);
            return ActionResult.Success;
        }

Log file looks good but the product is not installed :(

Logfile:
Calling custom action TitusInstaller!Titus.Installer.CustomActions.CustomAction.IlluminateRemovePluginsOnUpgrade
INFO:  -----------------------------------------------------
record is: UpgradeCode = {<upgradeCode>}, VersionMin = 15.4.10.19, VersionMax = 15.4.10.19, Language = , Attributes = 768, Remove = , ActionProperty = REMOVEPLUGINS
SUCCESS:  -----------------------------------------------
IlluminateRemovePluginsOnUpgrade: The removal of the old Core Plug-ins from the system succeeded.
Action ended 18:52:53: CA_REMOVEPLUGINS_ONUPGRADE. Return value 0.

Any idea why this is not happening? I am at a total loss :(

Thanks,

Steve



-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Phill Hogland
Sent: November-24-15 1:05 PM
To: WiX Toolset Users Mailing List <wix-users at lists.wixtoolset.org>
Subject: Re: [wix-users] FW: Advice on an upgrade 

I think I would:
1) Configure your test PC Windows Installer policy to include:
HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Installer
Logging = voicewarmupx!
Debug=7

2) If use LOGVERBOSE on bundle.exe(or MSI package) command line

3) Remove CustomAction/@HideTarget while debugging this issue.

4) After the temporary rows have been added, add a debug line like (In C++ it is as follows.  I assume there is something similar in DTF)
                hr=WcaDumpTable("TableName");
                ExitOnFailure1(hr, "failed to dump table: %ls.", "TableName");

As I understand adding a temporary row to an MSI table the change only exists in memory for that particular instance.  So when working with a system object (file or registry, etc.), it is important to add the temporary row to ALL installation modes (Install, repair, uninstall) as the temporary row is not persisted to the MSI file.  I have not tried to add a temporary row to the Upgrade table, but I assume it would be wise to add the temporary row in all modes also.  Debugging changes that only happen in memory are more difficult than inspecting the MSI file.

Phill

-----Original Message-----
From: wix-users [m[Steven Ogilvie] Anailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Steven Ogilvie
Sent: Tuesday, November 24, 2015 10:56 AM
To: WiX Toolset Users Mailing List <wix-users at lists.wixtoolset.org>
Subject: Re: [wix-users] FW: Advice on an 
How can you verify that adding the record worked?

I do a try catch and nothing is logged as an error but the product is still installed...

How do I verify if the upgrade table was actually created properly? Is the MSI updated in the Upgrade table?

I look at my MSI log file and search UPGRADINGPRODUCTCODE and the one I am looking for is not there....

I looked at Christopher's blog: http://blog.iswix.com/2008/07/dynamic-windows-installer-ui.html and used his example

So C# code:
        [CustomAction]
        public static ActionResult RemovePluginsOnUpgrade(Session session)
        {
            try
            {
                if (session == null)
                {
                    throw new ArgumentNullException("session");
                }

                //record.SetString(1, "{0C719557-xxxx-xxxx-B55E-xxxxxxxxxx}");  // UpgradeCode
                //record.SetString(2, "15.4.10.19");                              // VersionMin
                //record.SetString(3, "15.4.10.19");                              // VersionMax
                //record.SetString(4, "");                                        // Language
                //record.SetInteger(5, 0x00000300);                               // Attributes
                //record.SetString(6, "");                                        // Remove
                //record.SetString(7, "REMOVEPLUGINS");                           // ActionProperty


                InsertRecord(session, "Upgrade", new object[] { "{0C719557-xxxx-xxxx-B55E-xxxxxxxxxxxx}", "15.4.10.19", "15.4.10.19", "", 0x00000300, "", "REMOVEPLUGINS" });

               
            }
            catch (Exception ex)
            {
                WriteErrorLogInstall(session, "IlluminateRemovePluginsOnUpgrade failed: ", ex, true);
                return ActionResult.Failure;
            }

            WriteSuccessLogInstall(session, "IlluminateRemovePluginsOnUpgrade: The removal of the old Core Plug-ins from the system succeeded.", true);
            return ActionResult.Success;
        }

        private static void InsertRecord(Session session, string tableName, object[] objects)
        {
            try
            {
                if (session == null)
                {
                    throw new ArgumentNullException("session");
                }

                var db = session.Database;
                var sqlInsertSring = db.Tables[tableName].SqlInsertString + " TEMPORARY";
                var view = db.OpenView(sqlInsertSring);
                view.Execute(new Record(objects));
                view.Close();
            }
            catch (Exception ex)
            {
                WriteErrorLogInstall(session, "InsertRecord failed: ", ex, true);
            }

            WriteSuccessLogInstall(session, "InsertRecord: Inserting a new record into the current MSI database succeeded.", true);
        }

Calling the custom action code: 
<!-- On upgrade we want to remove the Core plug ins only if Client or Admin are not installed -->
    <CustomAction Id="CA_Set_RemovePluginsOnUpgrade" Property="CA_REMOVEPLUGINS_ONUPGRADE" Value="[ADMIN_GUID]|[CLIENT_GUID]|[CLIENT_MSI_GUID]|[PLUGIN_GUID]" HideTarget="yes"/>
    <CustomAction Id="CA_REMOVEPLUGINS_ONUPGRADE" BinaryKey="BIN_CustomAction" DllEntry="RemovePluginsOnUpgrade" Impersonate="yes" Execute="immediate"  Return="asyncWait"/>

<!-- Remove Core Plug-ins on upgrade -->
      <Custom Action="CA_Set_RemovePluginsOnUpgrade" Before="RemoveExistingProducts">WIX_UPGRADE_DETECTED</Custom>
      <Custom Action="CA_REMOVEPLUGINS_ONUPGRADE" After="CA_Set_RemovePluginsOnUpgrade">WIX_UPGRADE_DETECTED</Custom>
    </InstallExecuteSequence>

-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Phill Hogland
Sent: November-23-15 4:53 PM
To: WiX Toolset Users Mailing List <wix-users at lists.wixtoolset.org>
Subject: Re: [wix-users] FW: Advice on an upgrade.. 

I don't really have ideas, except to review when it is scheduled and when the Update entry that you were expecting in the log was scheduled.

I starred at it for a while but I don't use DTF so not really too familiar with that approach.  For my C++ CA, I setup a Lux project and then attach the debugger to the CA when the unit test is running to debug it.

-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Steven Ogilvie
Sent: Monday, November 23, 2015 3:26 PM
To: WiX Toolset Users Mailing List <wix-users at lists.wixtoolset.org>
Subject: Re: [wix-users] FW: Advice on an upgrade

I am using a C# CA DLL

Here is what I have in my WiX project:

<!-- On upgrade we want to remove the Core plug ins only if Client or Admin are not installed -->
    <CustomAction Id="CA_Set_RemovePluginsOnUpgrade" Property="CA_REMOVEPLUGINS_ONUPGRADE" Value="[ADMIN_GUID]|[CLIENT_GUID]|[CLIENT_MSI_GUID]|[PLUGIN_GUID]" HideTarget="yes"/>
    <CustomAction Id="CA_REMOVEPLUGINS_ONUPGRADE" BinaryKey="BIN_CustomAction" DllEntry="RemovePluginsOnUpgrade" Impersonate="yes" Execute="immediate"  Return="asyncWait"/>


<Custom Action="CA_Set_RemovePluginsOnUpgrade" Before="RemoveExistingProducts">WIX_UPGRADE_DETECTED</Custom>
      <Custom Action="CA_REMOVEPLUGINS_ONUPGRADE" After="CA_Set_RemovePluginsOnUpgrade">WIX_UPGRADE_DETECTED</Custom>
    </InstallExecuteSequence>

Custom Action DLL (for now just trying to get it to write to the DB temporarily...

[CustomAction]
        public static ActionResult RemovePluginsOnUpgrade(Session session)
        {
            try
            {
                if (session == null)
                {
                    throw new ArgumentNullException("session");
                }

                // Now check to see if Registry exits for previous version...

                // Now execute the database change
                TableInfo info = session.Database.Tables["Upgrade"];

                Record record =
                    session.Database.CreateRecord(info.Columns.Count);
                record.FormatString = info.Columns.FormatString;
                record.SetString(1, "{<The upgrade GUID>}");  // UpgradeCode
                record.SetString(2, "15.4.10.19");                              // VersionMin
                record.SetString(3, "15.4.10.19");                              // VersionMax
                record.SetString(4, "");                                        // Language
                record.SetInteger(5, 0x00000300);                               // Attributes
                record.SetString(6, "");                                        // Remove
                record.SetString(7, "REMOVEPLUGINS");                           // ActionProperty

                session.Message(
                        InstallMessage.User + (int)MessageBoxIcon.Information + (int)MessageBoxButtons.OK, record);
                
                session.Database.Execute(info.SqlInsertString + " TEMPORARY", record);
                
            }
            catch (Exception ex)
            {
                WriteErrorLogInstall(session, "RemovePluginsOnUpgrade failed: ", ex, true);
                return ActionResult.Failure;
            }

            WriteSuccessLogInstall(session, "RemovePluginsOnUpgrade: The removal of the old Core Plug-ins from the system succeeded.", true);
            return ActionResult.Success;
        }


This was the upgrade table that worked:

<!-- On in place upgrade we want to remove the Core Plug-ins from 4.4 RTM -->
    <!--<Upgrade Id="{<the upgrade code from plugin MSI>}">
      <UpgradeVersion Property="REMOVEPLUGINS" IncludeMaximum="yes" IncludeMinimum="yes" Minimum="15.4.10.19"  Maximum="15.4.10.19"/>
    </Upgrade>-->


It looks like it worked (i.e. no errors) but the log file does not have an UPGRADE string in the log file for that upgrade code... 

Any idea?

Thanks,

Steve

-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Phill Hogland
Sent: November-23-15 12:38 PM
To: WiX Toolset Users Mailing List <wix-users at lists.wixtoolset.org>
Subject: Re: [wix-users] FW: Advice on an upgrade... 

I would like to help you but I cannot post code in this situation as my implementation relates to some rather sensitive business rules.  But searching for  WcaAddTempRecord  the wix source with a text editor shows four places at least where temporary rows are being added to standard MSI tables at run time.   The behavior in the GamingExtension was the simplest for me to follow and understand.  I have not considered the details of the Upgrade table specifically, but when you detect the MSI that you want to remove, you would call WcaAddTempRecord to add the info to the Upgrade Table in an immediate CA.  MSI then processes the table as it would in any case and there is no deferred CA.

One of the entries in the wix source looks like this:
    hr = WcaAddTempRecord(&hView, &hColumns, 
        L"Registry",            // the table
        NULL,                   // we don't care about detailed error codes
        1,                      // the column number of the key we want "uniquified" (uniqued?)
        6,                      // the number of columns we're adding
        L"WixGameExplorer",     // primary key (uniquified)
        msidbRegistryRootLocalMachine,
        wzRegKey,
        L"GDFBinaryPath",
        wzGdfPath,
        wzComponentId);
    ExitOnFailure(hr, "failed to add temporary registry row for GDFBinaryPath");


-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Steven Ogilvie
Sent: Monday, November 23, 2015 10:15 AM
To: WiX Toolset Users Mailing List <wix-users at lists.wixtoolset.org>
Subject: Re: [wix-users] FW: Advice on an upgrade... 

Phill
Do you have an example of this?

It is too bad we can't conditional upgrade (in the case where I want to just uninstall an old MSI that is no longer part of the product...)

Steve

-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Phill Hogland
Sent: November-18-15 4:04 PM
To: WiX Uses (wix-users at lists.wixtoolset.org) <wix-users at lists.wixtoolset.org>
Subject: [wix-users] FW: Advice on an upgrade... 

Sorry - Upgrade table.

-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Phill Hogland
Sent: Wednesday, November 18, 2015 3:02 PM
To: WiX Toolset Users Mailing List <wix-users at lists.wixtoolset.org>
Subject: Re: [wix-users] Advice on an upgrade... 

How about a semi-CA that adds entries to the Update table if the configurations of concern are detected, and scheduled prior to RemoveExistingProducts?  (I have not do this but I did use a semi-CA for another purpose and it worked slick).   I found that searching the wix source for WcaAddTempRecord was the most helpful implementation examples.  There is also a Joy-of-Setup blog but the function prototype has changed from those details.

-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Steven Ogilvie
Sent: Wednesday, November 18, 2015 2:43 PM
To: WiX Toolset Users Mailing List <wix-users at lists.wixtoolset.org>
Subject: Re: [wix-users] Advice on an upgrade...

Hi Phil and all,

Sigh, okay I had to scrap the Upgrade code :(

I have two apps (call them X and Y apps) that have already been released that are using the same MSI (Plugins installer) as part of their install

In version A of my newer app (call it Z)  it was installing this MSI (Plugins installer) as well In Version B which we will be releasing soon, I have moved the DLL's that that other MSI (Plugins installer) was installing into our app MSI

The issue is that I can install either X or Y and my newer app Version A (call it Z) and they can coexist because I set " SharedDllRefCount "with the components of the MSI (plugins installer) so if you install X (or Y) then install Z (version A) then uninstall either of them, the other will continue to work...

We realized this was not going to work with version B of app Z so I moved the DLL's from the Plugins installer to my app Z

So my delima is that on Upgrade of Z (to version B) I don't want to remove the Plugins installer if apps X or Y is installed

So I have created a custom action that checks for apps X and Y and if they exist I don't uninstall the Plugins MSI

If X or Y does not exist I run MSIEXEC.exe /X <plugins GUID> using ProcessStartInfo and Process.Start(info)

However the installer is failing:
Failed to grab execution mutex. System error 258.
MainEngineThread is returning 1618

I have the custom action set up as:

<!-- On upgrade we want to remove the 4.4 RTM Core plug ins only if Client or Admin 4.4 RTM are not installed -->
    <CustomAction Id="CA_Set_RemovePluginsOnUpgrade" Property="CA_REMOVEPLUGINS_ONUPGRADE" Value="[ADMIN_GUID]|[CLIENT_GUID]|[CLIENT_MSI_GUID]|[PLUGIN_GUID]" HideTarget="yes"/>
    <CustomAction Id="CA_REMOVEPLUGINS_ONUPGRADE" BinaryKey="BIN_CustomAction" DllEntry="RemovePluginsOnUpgrade" Impersonate="no" Execute="commit" Return="asyncWait"/>

Then in InstallExecuteSequence I set the sequence to:

<Custom Action="CA_Set_RemovePluginsOnUpgrade" Before="InstallFinalize">WIX_UPGRADE_DETECTED</Custom>
<Custom Action="CA_REMOVEPLUGINS_ONUPGRADE" After="CA_Set_RemovePluginsOnUpgrade">WIX_UPGRADE_DETECTED</Custom>

My custom action code RemovePluginsOnUpgrade works great detecting if X or Y is installed and based on that whether or not to run the uninstall of the Plugins installer...

The issue is that of course the uninstall fails because another install is running (the calling MSI)

Any advice how to proceed???

Thanks,

Steve

-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Steven Ogilvie
Sent: November-17-15 2:07 PM
To: WiX Toolset Users Mailing List <wix-users at lists.wixtoolset.org>
Subject: Re: [wix-users] Advice on an upgrade...
Excellent, I just tried that and it works :)

<!-- On in place upgrade we want to remove the Core Plug-ins from 4.4 RTM -->
    <Upgrade Id="THE-UPGRADE-GUID-OF-OLD-INSTALL">
      <UpgradeVersion Property="REMOVEPLUGINS" IncludeMaximum="yes" IncludeMinimum="yes" Minimum="15.4.10.19"  Maximum="15.4.10.19" />
    </Upgrade>

Steve

-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Phil Wilson
Sent: November-17-15 2:03 PM
To: 'WiX Toolset Users Mailing List' <wix-users at lists.wixtoolset.org>
Subject: Re: [wix-users] Advice on an upgrade...

You should be able to add an Upgrade element naming the UpgradeCode of that Plugins MSI. There's nothing about major upgrades that requires only one older product to be upgraded/uninstalled. 
Phil  

-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Steve Ogilvie
Sent: Tuesday, November 17, 2015 10:13 AM
To: WiX User List
Subject: [wix-users] Advice on an upgrade...

Hi folks,
Version 1 of our product (which has gone out the door) installs a MSI for a bunch of plugins, as well as our product MSI (so 2 MSI's).
Version 2 of our product (which hasn't been released yet) had merged the files from that MSI, into our product MSI.i.e. the 12 files from the plugin MSI are now in our product MSI.
I tested an in place upgrade of Version 2 overtop of Version 1, all works well EXCEPT that the Plugins MSI does not get uninstalled and remains behind.
Any idea on how to safely uninstall the Plugins MSI on upgrade with version 2?
Thanks,
Steve 		 	   		  


 



 
This message has been marked as Public by Steven Ogilvie on November-25-15 6:57:56 PM.

The above classification labels were added to the message by TITUS Message Classification. 
For more information visit www.titus.com.


More information about the wix-users mailing list