[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