[wix-users] Programmatically removing a bundle

Rob Mensching rob at firegiant.com
Wed Feb 17 09:25:56 PST 2016


IIRC< Burn uses the upgrade code to detect versions of itself so provider key isn't necessary

_____________________________________________________________
 Short replies here. Complete answers over there: http://www.firegiant.com/


-----Original Message-----
From: wix-users [mailto:wix-users-bounces at lists.wixtoolset.org] On Behalf Of Dan Parker
Sent: Wednesday, February 17, 2016 9:22 AM
To: WiX Toolset Users Mailing List <wix-users at lists.wixtoolset.org>
Subject: Re: [wix-users] Programmatically removing a bundle

I have a similar issue where I had to automatically deploy a bootstrapper to N PCs first by uninstalling the old one, without any user interactivity. Here's what I had to do to get this to happen:

First in the bundle WXS, set a dep:ProviderKey on the Bundle element. This is important, because you have a stable bundle bundle provider key to look up the installed bundle in the ARP registry key.

Second in my code, I wrote these two methods to look up something in the ARP by bundle provider key and run the uninstall script associated with it (sorry, it's C#):

        static int RunUninstallBootstrapper(string testSuiteName)
        {
            string[] uninstallLocations = new string[]
            {
                @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
                @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
            };
            string logFileName = GetCustomLogPath(testSuiteName, "uninstall.txt");
            int rc = 0;

            Console.Out.WriteLine("Uninstalling test suite. Log={0}", logFileName);

            using (StreamWriter sw = new StreamWriter(logFileName, true))
            {
                sw.AutoFlush = true;

                foreach (string productId in Properties.Settings.Default.TestSuiteProductIds)
                {
                    sw.WriteLine("Looking for '{0}'", productId);
                    Installer type;
                    string productCode = GetProductId(productId, out type);
                    sw.Write("Type: {0}  code: {1}", type, productCode);

                    if (type == Installer.Bundle || type == Installer.Exe)
                    {
                        foreach (string uninstallLocation in uninstallLocations)
                        {
                            using (RegistryKey uninstallKey = Registry.LocalMachine.OpenSubKey(uninstallLocation))
                            {
                                if (uninstallKey != null)
                                {
                                    sw.WriteLine("In key '{0}'", uninstallLocation);
                                    if (!ArpUninstall(sw, logFileName, productCode, type, uninstallKey, ref rc))
                                    {
                                        sw.WriteLine("Uninstaller failed. rc={0}", rc);
                                        return rc;
                                    }
                                }
                            }
                        }
                    }
                    else if (type == Installer.Msi)
                    {
                        MsiUninstall(sw, logFileName, productCode);
                    }
                    else
                    {
                        throw new InvalidOperationException();
                    }
                }
            }

            return rc;
        }

        static bool ArpUninstall(StreamWriter sw, string logFileName, string productCode, Installer installerType, RegistryKey uninstallKey, ref int rc)
        {
            foreach (string subKeyName in uninstallKey.GetSubKeyNames())
            {
                using (RegistryKey productKey = uninstallKey.OpenSubKey(subKeyName))
                {
                    if (productKey != null)
                    {
                        string compareString;
                        if (installerType == Installer.Bundle)
                        {
                            compareString = (string)productKey.GetValue("BundleProviderKey", String.Empty);
                        }
                        else if (installerType == Installer.Exe || installerType == Installer.Msi)
                        {
                            compareString = uninstallKey.Name;
                        }
                        else
                        {
                            throw new InvalidOperationException();
                        }
                        compareString = compareString.Trim();
                        string uninstallString = GetUninstallString(logFileName, productKey, installerType);

                        if (String.Compare(productCode, compareString, StringComparison.InvariantCultureIgnoreCase) == 0)
                        {
                            sw.WriteLine("Uninstalling product '{0}'", productCode);
                            sw.WriteLine("Uninstall string: '{0}'", uninstallString);
                            if (String.IsNullOrEmpty(uninstallString))
                            {
                                sw.WriteLine("Product does not specify an uninstall string. Skipping.");
                                if (rc == 0)
                                {
                                    rc = -1;
                                }
                                continue;
                            }

                            using (Process p = new Process())
                            {
                                string cmdExe = Path.Combine(Environment.SystemDirectory, @"cmd.exe");
                                uninstallString = @"/c """ + uninstallString + @"""";
                                sw.WriteLine(@"Running command: ""{0}"" {1}", cmdExe, uninstallString);
                                p.StartInfo.FileName = cmdExe;
                                p.StartInfo.CreateNoWindow = true;
                                p.StartInfo.Arguments = uninstallString;
                                p.StartInfo.UseShellExecute = false;
                                if (!p.Start())
                                {
                                    sw.WriteLine("Failed to start uninstaller.");
                                    if (rc == 0)
                                    {
                                        rc = -1;
                                    }
                                    return false;
                                }
                                p.WaitForExit();
                                sw.WriteLine("Exit Code: '{0}'", p.ExitCode);
                                rc = p.ExitCode;
                                break;
                            }
                        }
                    }
                }
            }
            return true;
        }

It worked for my bundle, but you may have to tweak it for yours.


More information about the wix-users mailing list