Detect newer version of Wix bootstrapper - wix

I have a managed wix bootstrapper and I noticed that I can provide a url for an updated version of the bootstrapper for upgrade detection. However it seems this only runs if my bootstapper has been installed before. Is there any default way for burn to detect a newer version of the bootstrapper before installing the current version? What I would like is if a customer has a copy of a legacy bootstrapper and runs it to install a new machine that the user is provided an option to download the new bootstrapper and run it instead. I assume I could code all this up from scratch in custom bootstrapper but wanted to be sure that I wasn't reinventing the wheel. It seems like there would be given that most of this is already implemented with the update detection.

You can always check the reg keys for product version and compare it with your latest.

From the docs, http://wixtoolset.org/documentation/manual/v3/xsd/wix/update.html, this feature is not available yet and you would have to build it into your custom WPF bootstrapper application.

After further testing and investigation it looks like I was incorrect about how this works. The detectupdateBegin event does get called even if the bundle hasn't been installed before. You can either allow Wix to consume an atom feed using the app syndication format. If you use this format then the engine will return the latest version in the feed. Otherwise you have to roll your own update service and put the call in the detectupdateBegin event handler. Be sure not to set the result to Ok otherwise the engine will look at your service url and try to process it like an app syndication feed and return an error.
One you detect an update you will need to call Engine.SetUpdate and then call Plan with InstallAction of UpdateReplace.

Related

Existing Uninstaller Broken During Upgrade - Patch MSI?

I wrote a custom action to help during upgrade of my product (from 1.0 to 1.1). Now I need to upgrade from 1.1 to 1.2 but the existing uninstaller is failing during upgrade. I got the execution conditions of my custom action wrong. (Lesson learned, always test upgrading to the next version before deploying).
Right now it seems my best option is to modify the InstallExecuteSequence table in the existing .msi to disable the failing custom actions. I'll have to create another custom action to browse the registry, locate the existing .msi in C:\
Windows\Installer, patch it, and then continue with the upgrade. This sounds like a terrible, error prone solution, but I'm really at a loss. This was supposed to be an automatic, silent upgrade pushed down from a remote cloud.
Another option would be to write a batch script to uninstall the existing product, then execute the new installer.
Any advice?
EDIT This question is already answered here: I screwed up, how can I uninstall my program?
The supported way to do this is a patch (by which I mean an MSP file, not coding to alter the cached MSI file). That's by far the most straightforward way to get out of the situation. After that, do the upgrade. Using WiX you could probably put the MSP and the upgrade in a bundle.
In any case, you wouldn't do your proposed change with another MSI. A small executable can do what you propose, and:
MsiGetProductInfo (ProductCode, …, INSTALLPROPERTY_LOCALPACKAGE)
is how you find the cached MSI.
Conditioning: What condition did you set on the failing custom action? And more importantly, what is the new condition you are intending to use? It sounds like regular uninstall works but major upgrade fails? The typical problem is that uninstall fails altogether, and then the usual solution is a minor upgrade which I will quickly describe.
Minor Upgrade: Normally what I use is a minor upgrade to fix whatever is wrong in the current install's (un)installation sequence(s). A minor upgrade does not uninstall the existing installation, it upgrades it "in-place", and the uninstall sequence is hence never called and thusly you avoid all its errors from manifesting themselves. There is no need to browse to the cached MSI file and hack it manually if you do things correctly in your minor upgrade. The updating of the cached MSI will happen auto-magically by the Windows Installer Engine provided you install with the correct minor upgrade command line.
Future Upgrades: A minor upgrade will generally always work if you make it simple enough, but the problem is usually applying it since it often targets only a single, previous version. When you get to the next release and if you then use a major upgrade, you will see the error in your original MSI manifest itself on uninstall if you are upgrading an installation that never had the minor upgrade applied - in other words it is still the oldest version of your installation. This is generally solved by a setup.exe launcher which will install the minor upgrade if need be. The bad news is that you need to keep that update in every future release - if you want to avoid any upgrade errors. Or in a corporate environment you would use the distribution system to check what is already on the box and install accordingly. If your manual uninstall works correctly (but major upgrade uninstall fails), all you should need to do is to push an uninstall command line to msiexec.exe as the first command to run via your setup.exe I think. Then there is no need to include any minor upgrade binaries in your setup.exe launcher.
Detect & Abort?: Michael Urman's answer here explains how it might be difficult to make sure that the minor upgrade is present on the box before applying the next version of your software:
InstallShield fails because of a bad uninstall. He suggests making your package better at detecting whether a new upgrade can be safely applied.
Some Links:
how to omit a component when we try to build .msi using wix (on how patching is just a distribution mechanism for MSI upgrades that must already be working)
Is there any possible way to perform upgrade when Product codes for old and new versions are same? (on minor upgrades and their technical limitations)
Here is a hack that I got working, but based on the answers above it looks like it's not the preferred way.
[CustomAction]
public static ActionResult Patch11Installer(Session session)
{
string localPackage = NativeMethods.GetMsiInstallSource("{MY-PRODUCT-CODE}");
if (String.IsNullOrEmpty(localPackage))
{
session.Log("Failed to locate the local package");
return ActionResult.Failure;
}
session.Log($"Found local package at {localPackage}");
using (Database database = new Database(localPackage, DatabaseOpenMode.Direct))
{
foreach (string action in new string[] { LIST OF CUSTOM ACTION NAMES })
{
session.Log($"Modifying condition for action {action}");
database.Execute($"UPDATE InstallExecuteSequence SET Condition='WIX_UPGRADE_DETECTED' WHERE Action='{action}'");
}
database.Commit();
}
return ActionResult.Success;
}
The custom action calls MsiGetProductInfo to query for the v1.1 MSI using the v1.1 product code which I obtained from installer log files. It then opens the MSI database and modifies the Condition property of the InstallExecuteSequence table for the list of custom actions that are failing. It changes the Condition from "UPGRADINGPRODUCTCODE OR WIX_UPGRADE_DETECTED" to "WIX_UPGRADE_DETECTED". UPGRADINGPRODUCTCODE is the property that's causing the uninstall to fail during a major upgrade as this property is passed to the uninstaller and contains the new product code; the product code for v1.2 in my case. Here is the custom action definition in my installer file.
<CustomAction Id="Patch11Installer" Return="check" Impersonate="yes" Execute="immediate" BinaryKey="MyUpgradeCustomActions" DllEntry="Patch11Installer" />
I'll look into implementing a minor upgrade as suggested in other answers. I just thought I would leave this solution here.

WiX Upgrade with custom versioning

I got a problem. I want to upgrade my app during installation process, but I run into problem with versioning. I use version number in format e.g. 5.5.789.0, some new version has version number in format 5.5.12.1. I know that installer only works with first three numbers from version so MajorUpgrade is not suitable for me. New version would not be installed in this case. Is there a way in which I can check versions in some custom action and plan upgrade from there? I cannot change the versioning as app building goes through some automatic post-processes that also works only with first three numbers and it is not possible to change that behavior.
Thanks for suggestions.
EDIT:
I am using WiX#.
It's not obvious to me why you can't use the WiX majorupgrade element. The settings would be AllowDowngrades=yes, maybe AllowSameVersionUpgrades=yes.
Using Schedule=afterInstallValidate is (as the docs say) removes the old product entirely before installing the new upgrade.

Wix - During install/upgrade a Custom Action's conditions resolve to False when they shouldn't

The Setup
So I have a Custom Action in my InstallExecuteSequence that looks like this:
<Custom Action="UpdateConfigFile" After="InstallFinalize">NOT Installed OR Upgrading</Custom>
Where Upgrading is defined to:
<SetProperty After="SetFirstInstall" Id="Upgrading" Value="true">
WIX_UPGRADE_DETECTED AND NOT (REMOVE="ALL")
</SetProperty>
The Custom Action updates a web.config file with a value that is passed into the installer via a Property. It is a VB.Net function.
The Issue I'm Running Into
This Custom Action has always executed in many of our installers. But for a certain environment that we have in development, the conditions for it resolve to False on a install/upgrade scenario. It says "(condition is false)" in the MSI log.
The environment is used for development purposes such as testing the product after installed/updated.
What I'm Trying to Accomplish
I would like this to be resolved so that this environment can install our product successfully.
What I've Done So Far
I've installed the same installer to different Operating Systems such as Windows 10, 2012 R2, and 2016. The installer works just fine since the Custom Action runs as expected.
The troublesome environment is a Windows Server 2012 R2 machine. Which makes me even more confused.
I did some digging in and was only able to find this link: (https://blogs.msdn.microsoft.com/heaths/2006/07/11/why-a-custom-action-may-not-run/#comments)
From the link's suggestion, I think it is really odd if a dependency was missing because the same installer works on other machines.
So I'm pretty stumped at this point. Any help or direction would be very much appreciated. If I'm not being clear enough, feel free to ask for more clarification. Please and thank you.
Just some comments to get going, this isn't a real answer:
First things first: in order to be passed properly to deferred mode (InstallExecuteSequence) properties should be UPPERCASE (public properties) and they should be listed in the SecureCustomProperties delimited list of "safe properties" to pass to deferred mode.
Other than uppercasing it, I wouldn't set a property called Upgrading like that, I would rather use the "raw" conditions for the custom action in deferred mode (InstallExecuteSequence).
Here is a cheat sheet of common conditions from Flexera (makers of Installshield): Common MSI Conditions Cheat Sheet. And here is a direct link to the PDF.
You can have a look at this old post: How to add a WiX custom action that happens only on uninstall (via MSI)?. I have never had the time to test all those conditions, but at face value it looks correct.
Some notes about the special property UPGRADINGPRODUCTCODE.
UPGRADE:
Questions:
That Windows Server 2012 R2 machine - is there anything special about it? Is it tightened for security? What is its task or purpose on the network?
What is the actual implementation of UpdateConfigFile - is it a script, a compiled DLL written in C++, a managed DLL written in a .NET language, or something else? Maybe an EXE file?
Does any of this sound familiar: Installer fails on Windows Server 2012 R2
Did you verify that the correct version of the .NET framework is installed on this problem server? Does the function run interactively? Try running that VB.NET function interactively on that computer via a test harness EXE if it is a DLL function. Or just run it straight is it is an EXE file outright.
The issue is likely to be that you are scheduled after InstallFinalize (which is not good, see later) because the Upgrading property is not public (not uppercase). If you change the condition to WIX_UPGRADE_DETECTED AND NOT (REMOVE="ALL") it should work, assuming:
WIX_UPGRADE_DETECTED is the actual property associated with the major upgrade, such as from the major uypgrade element.
WIX_UPGRADE_DETECTED is in SecureCustomProperies.
Actions after InstallFinalize are generally not recommended because if they fail (in your case screw up the config file) then there is not much that can be done (such as roll back to a correct config file). It's effectively after the install, so it's also easier to do the config changes in the app when the upgraded version runs for the first time.
After helping the team responsible for the environment, we found out that it was a certain scenario that was causing this issue. Digging deep into the MSI log further, we found that a previous Custom Action running, also after InstallFinalize, was returning a Failure Action Result. Since that happened, the following Custom Actions such as my UpdateConfigFile Custom Action, don't execute. Resulting in the "(condition is false)" entry in the log.
Once we figured that out, I was able to reproduce it on my local environment.
Since these Custom Actions are after InstallFinalize, I thought that those Custom Actions would still run if one failed because we're past the point of the installer being able to do a Rollback. But I was wrong and now I know.
Thanks for everyone helping me out in trying to figure out this issue. I was getting worried that I was going to try to figure this out for days and start pulling my hair out. XD

Windows msi: error 1316: the specified account already exists

The execution of a wix package from a bundle outputs "error 1316: The specified account already exists" during upgrade. How can a windows installer output this error code? I'm afraid there isn't much documentation about it.
We previously released a product consisting of a single msi package, and now we are preparing an upgrade which consists of a wix bundle containing a new version of this msi package. The product code and filename between the original msi package and the update haven't changed.
Edit: The msi package for now doesn't support upgrade. When the user needs to upgrade (whenever it's a major upgrade, minor upgrade or small update), he must first manually uninstall the previous package...
Edit 2: I just removed the references to util extension for compilation and the installer seems to work fine... I still need to fully test it though.
Like MrFusion, I ran into this problem with the uninstall/install of another program. Unfortunately, the link in that answer is no longer valid, and redirects to a page that lists many easy fix solutions, except for the only one that will help. That one, "Program Install and Uninstall", is currently available at: https://support.microsoft.com/en-us/help/17588/fix-problems-that-block-programs-from-being-installed-or-removed
It solved the problem for me.
I had his same issue and since win10 doesn't allow you to run the fixit tool from the web, I did the following hack to uninstall Asus Smart Gesture on my Windows 10 laptop.
You need to fake the MS site into thinking your pc isn't Win10. I installed a Chrome add-in that allowed me to change the user-agent of the chrome browser to thinking I was IE9 and previous version of windows: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
This allows you to see the fixit button and to download a portable version of the tool (in case you need to use it on non-networked clients)
I downloaded and extracted to my downloads library in a folder called fixitp.
If I run the exe directly, I get some nasty script error. What I did to get around that was to navigate to the Resources folder and then to the Troubleshooters folder.
I ran the Program_Install_and_Uninstall.diagcab which run and allowed me to uninstall successfully the Asus SmartGesture program.
I then installed a fresh version of ASUS's Smart Gesture from their site.
I suspect that any installed app that you can't uninstall can be resolved by this same process - just haven't run into any other that this on.
Good luck.
An upgrade MSI requires the MSI to have a new ProductCode, an incremented ProductVersion (in the first 3 fields) and the same UpgradeCode. So it's not clear to me that you're actually getting an upgrade, depending on what the Burn part thinks you are doing. It can't do an upgrade because you have the same ProductCode. (You need a MajorUpgrade element in your MSI to do a proper upgrade). So there is some doubt as to whether you're getting an actual full upgrade. If your intent is to replace the installed MSI with a full upgrade, and a higher versioned product then use MajorUpgrade.
So Burn may have decided to do an in-place update by reinstalling the MSI file (and that's more like a patch than an update), and that's relevant because you don't say whether you have any custom actions or WiX util functions (they are still custom actions) that create a user account. If you do, then the most likely reason for your error is that Burn reinstalled your new MSI as an update by reinstalling the MSI file, and some custom action simply ran again, and yes, that user is still there because there has not been an actual uninstall that would delete it. Or the ProductVersion of your MSI is the same and you got a maintenance mode repair, so a custom action would run again.
I'd get a verbose log of the upgrade to see exactly what's going on.
There's a lot of guesswork here because you say you want an upgrade but your MSI isn't built to actually do an upgrade, and you don't say if you have WiX util User in there to create a user account. You also don't say if you have incremented the ProductVersion of your new MSI either, so again that results in more guesswork as to what Burn might do. The verbose log would show whether it's a custom action issue or something else, what kind of update (if any) that you're doing.
I ran into this recently.
For me this worked for me by keeping the names of both the older version and the newer version of the installer same.
No idea why it works, but some of the best practices while working with msi is to keep the name of the installers same.
A couple of links to support the case –
http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/KB2918614-td7596942.html
https://community.flexerasoftware.com/showthread.php?189045-Upgrade-failed-with-Error-1316&highlight=error+1316+account+already+exists
I had the same issue uninstalling another program. This Fix-It solved the problem for me: https://support.microsoft.com/en-us/mats/program_install_and_uninstall/en
Update note: it's no longer necessary to emulate an older user-agent on Windows 10 to download the fix-it file.
Update 2: As Chris Johnson mentioned, Microsoft has discontinued Easy Fix, so the link above does not work anymore.
You probably need to change the 'packagecode' (note: NOT 'ProductCode') for the MSI. You'll find it in the Summary Information Stream.
Just encountered this myself when trying to create an Upgrade MSI package. Using Orca to change the 'packagecode' fixed it.
For me, that happening with nodejs when I was trying to uninstall it. What solved in my case was downloading the same version of nodejs that was installed (8.11.1) and uninstalling that from msi installer file.

How to author a WiX Burn bundle including a ComPlus proxy installer

We have the scenario with an application with one .Net- and one VB6-client that should be deployed as a single bundle. The VB6 part on its hand contains its binaries as well as an ComPlus proxy. The proxy's installer is generated using COMAdminCatalog.ExportApplication. The three parts is bundled together with WiX Burn and uses the standard bootstrapper application. The creation of the bundle is part of an automatic build and deploy chain.
The problem is how to handle the proxy's installer in the bootstrapper.
There is no way of controlling the product- and upgrade code or version in COMAdminCatalog.ExportApplication. Thus a previous version can't be upgraded by a new. (At least I have not found a way, is there any?)
The msi generated from COMAdminCatalog.ExportApplication does not handle repair or reinstall. Will result in error and rollback of whole bundle.
Two versions of the proxy cannot be installed at the same time. Second one will result in error and rollback.
I have had some progress wrapping the complusproxy.msi in a bat script and use ExePackage instead of MsiPackage. The script begins with removing any previous version of the complusproxy. The problem with this is to get all different install/upgrade/uninstall-scenarios to work correctly.
I'm considering the option to edit the generated complusproxy.msi to get control of the upgrade code and version and add that to the build process.
It feels like I'm trying complex work arounds and it should be a correct, better way of doing it. What would be a better or good enough approach to solve it?