WiX installer - how can I remove installed application and re-install it at the same run - wix

I have a custom installer based on WiX technology which is install several .vsix packages into Visual Studio.
If this packages are already installed, the installer offers to remove them. After the removal process is completed, the installer exits.
It's normal behaviour, but I need to offer the user re-install this packages (optionally) before exit. I mean optional mode to uninstall the previous version and install the new one (or the same) with a single run of the installer.
How to implement this in WiX ?

I suspect your custom installer could be made a little smarter. There are plenty of APIs (such as MsiQueryProductState) that will tell you if that exact ProductCode is installed, and ways to get the version (MsiGetProductInfo). My guess is that your custom installer is just firing off all the MSI installs without checking if they are already installed, hence the Remove prompts.
Your general plan should be to have some data available to your custom installer that it can use to find out what's already installed and what the versions are, and then compare these with what you are about to install. Use those APIs. If the product is already installed then skip the install. If you have a newer version (that you built with the WiX MajorUpgrade element) then just install it because it will replace the existing older one.
There's nothing I can think of in WiX that would automatically reinstall a product that your custom installer caused removal of by re-installing it and prompting the user to remove it, if that's what's going on.

Related

Removing an MSI package in a bundle without including the source

I have a WIX Bootstrapper Burn bundle which contains 4 MsiPackages and has been released in production. Our latest version of the bundle is to no longer ship one of the packages and should uninstall the package should it exist. What is the best way to uninstall the MsiPackage without providing the entire msi in the bundle?
I have tried:
Removing the PackageGroup from the chain entirely - This leaves the product behind.
Adding the MsiPackage and setting the installlevel to 0 - This needs a very large payload as the msi that is being removed is large.
I also tried using product search to find the state
<util:ProductSearch Id="AppX" UpgradeCode="XXXXXX-XXXX-XXXX-XXXX-XXXXXXXX" Result="state" Variable="APPXSTATE" />
but tried to hook it up to an ExePackage to run msiexec /x UpgradeCode but I figure is the wrong way to uninstall.
Whats the best way for me to purge msi with UpgradeCode X if it exists in this newer burn installer?
Thanks
Note: I am not aware of any auto-magic constructs to use in collaboration with util:ProductSearch to uninstall existing MSI
installations.
Upgrade Table: I assume the four different products have different upgrade codes "per family"? If so - and if you are positive it will never need to be installed again - then I suppose you could specify that it should be uninstalled via a major upgrade for one or more of the packages you will keep delivering. Note: It might be possible to uninstall even if all setups share the same upgrade code, but that requires a lot more care and testing.
This solution involves adding the upgrade code for the MSI you want to remove to the upgrade table of those MSI setups you want to preserve with a version range specified that will uninstall all "known prior editions". Technical details for how to do this can be found here: Adding entries to MSI UpgradeTable to remove related products. As stated it is enough to do so for one of the products that will remain, but you can do it for all of them to be sure. No errors should result if the product has already been uninstalled. I might want to set a tighter range than what is shown in that technical sample for the versions targeted.
ExePackage: It should be possible to uninstall as you have suggested by using an ExePackage instead. It could run msiexec.exe directly I suppose, or maybe launch a VBScript, Powershell script or even a batch file or your own EXE file compiled from C++ or C# (the latter with unfortunate runtime requirements). I have never tried this approach.
Please note that you do not uninstall by upgrade code in the fashion you do with msiexec.exe /x UpgradeCode - at least I have never been able to make that work (not tested for a while). Instead you need to uninstall via product code (How can I find the product GUID of an installed MSI setup?), OR you can use VBScript and MSI API automation to uninstall by using the Installer.RelatedProducts function and then kicking off uninstall that way as shown here: Powershell: Uninstall application by UpgradeCode. This is similar to what happens when Windows Installer processes the Upgrade Table. All releated products - those sharing the same upgrade code - are enumerated and you can handle them as you do so.
Some Links:
Powershell: Uninstall application by UpgradeCode
WIX (remove all previous versions)
Wix upgrade goes into maintenance mode and never does upgrade

Is there anyway to upgrade a .exe installed program with .msi without a double entry in ARP?

I am currently using WiX Toolset to build my installer. This tool is very nice but recently I encountered a problem. When I installed my program with .exe, then upgrade it with .msi, there is a double-entry in Add/Remove Program. Is there anyway to prevent the installer add double entry? Thanks!
It's not clear from your post if you have followed the rules for a major upgrade, such as use the same UpgradeCode, new ProductCode and PackageCode, increment ProductVersion in the first three fields, have upgrade logic in place in the MSI (such as major upgrade element). You'd need to supply your WiX source for these in the old and upgrade builds to see the differences. A verbose log would also help, installing the MSI with a command line that includes /l*vx [path to log file]
If those rules have been followed, the main reason for failure to upgrade is the one was per user and the other is per machine (or vice versa). One context will not upgrade the other. If this is the case the log will have an entry somewhere with FindRelatedProducts referring to an installed product in another context.
All this also assumes that the original install you did was MSI-based underneath the exe. If it was not, and it was some other install software that is not using an MSI file then there is no such thing as an automatic upgrade. You'd need to find some none-MSI way to uninstall the older product. A typical way is to find the UninstallString in the registry for that product and run it. Depending on the software used, that command can be parsed to add a silent option.

Should a WiX web installer and stand-alone installer both show up in Add/Remove programs?

We have two WiX installers that use our own BA. One installer gets all the packages from the web, while the other gets all the packages from the exe. We call them "Web" and "Full" installers.
We have a case where a user might install one package from the web installer and a different package form the full installer. It probably won't happen often but it could happen. When the user does this, we have two entries in the Add/Remove programs control panel. Since we didn't name the installers differently, it looks like the installer is installed twice.
My question is, if the only difference between two installers created with WiX is the way the packages were acquired, shouldn't it just appear once in Add/Remove programs? Do I need to set a code somewhere to say it is the same installer?
I guess we could just name them differently so that a "Web" and a "Full" installer appeared in Add/Remove Programs, but when you run either one, both packages show up for uninstallation because both installers know about them. It's not like the web installer only shows the package that was installed through it and the full the package that was installed through it.
Any comments are appreciated.
In a version upgrade scenario, using the same UpgradeCode for both <Bundle...> packages is enough to indicate both installers are the same product. For example, if you first install package V1.0 and later install package V1.1 (where both packages use the same upgrade code) Package V1.1 replaces Package V1.0 in Add/Remove Programs.
Unfortunately the burn engine does not support same version upgrades. If you have different packages with the same upgrade code and the same version, both packages will appear in Add/Remove Programs. For more information on burn not supporting same version upgrades see: http://wixtoolset.org/issues/3746/.
Installing two different packages with the same upgrade code and version is well behaved. For example, if you install both packages and subsequently remove one of them, the resources in the first package remain installed, even though the same resources are also in the second package.
Installing two different packages with the same upgrade code and version, then later installing a third package with the same upgrade code but a higher version is also well behaved. The third package replaces the first two packages!
Your suggestion of varying the name of the packages to differentiate them in Add/Remove Programs sounds the most pragmatic way forward. Having two entries does not appear to compromise the installation state, and upgrades appear to be handled without issues.

Having an issue with WIX upgrade

Having an issue with WIX installer upgrade. Previously we had 2 version of installers 1 for per-machine and another for per-user.
Currently we have developed a dual mode MSI.
The dual mode MSI upgrades the PerUser version (on PC 1) of previous installer when install for yourself option is selected but when install for all (on PC 2 ) is selected it install a new product
Is it some wrong that we are doing or is have to set some properties. We are using WIX.
Please help
Per-user installs allow the installation of the same product multiple times for different users - and in different versions too. This makes upgrades and patches rather difficult to deal with, and I dislike this per-user concept altogether. I prefer to set the installer per-machine as standard. I don't feel that much is lost in functionality, but a lot is gained in managability. Though this is not an answer to your question, it is worth pointing out that per-user installs is a flawed concept - at best.
I don't know if it is an option to set your installer per-machine, but I found a way to migrate installs from per-user to per-machine automagically by using Installshield and its custom ISSetAllUsers custom action. The procedure is described here:
windows Installer - uninstalling previous version when the versions differ in installation policy (per-user, per-machine)
Wix does not feature such a custom action as far as I know, but you could write your own custom action using the Win32 API call ::MsiEnumRelatedProducts() as described by Rob Mensching here: how to change from per user to all user installation?
Here is a similar post for reference: How can a perUser installation program deal with a perMachine older version of the program?
Here is a blog describing (further) issues with per-user installs: Understanding “Per-User” or “Per-Machine” context for application Setup packages.
Let me add a couple of further comments:
You can have per-user settings without a per-user install. This is no problem, just have the application set up the userprofile on launch. I prefer to install all resource files and settings per-machine and have the application copy them to each user for first launch initialization. This ensures that user settings are not entangled with your MSI at all.
It is rare to maintain two separate versions of the same product at the same time - hence users are all likely to use the same version of the product. Per-user is just more headache in this perspective.
The upgrade and patching logic involved in per-user installer scenarios beats me - it just doesn't make any sense to me. If there is a per-machine install already, does a per-user install make sense to you? Does this install the application one more time?
If per-user installs are still important, perhaps you can try ClickOnce (if it still works). Quote from Wikipedia: "...ClickOnce-deployed applications are considered 'low impact', in that they are installed per-user, not per-machine. No administrator privileges are required to install one of these applications. Each ClickOnce application is isolated from the others. This means one ClickOnce application is not able to 'break' another.". Per-user installs make more sense if they are hooked up to auto-updating and web-deployment.
If you had two setups before, it might be that you have two upgrade code and need to deal with both for the upgrade to work in all cases?
It has been a long time since I dealt with per-user stuff, but in general you must author your Upgrade table to include both upgrade codes for your setups to detect all flavours of your previous install. The upgrade table allows you to detect any number of prior installs that should be scheduled for uninstall before your new product gets installed.
The FindRelatedProducts MSI action will search all packages on the target machine in order to find any where the Upgrade Code property matches the value specified in the upgrade table.
Make a verbose log file as has been suggested:
msiexec.exe /I "File.msi" /QN /L*V "C:\Temp\msilog.log"
/I = run installation sequence
/L*V "C:\Temp\msilog.log"= verbose logging
/QN = run completely silently
I believe this is occurring because in your installer the default mode is Per-User hence it is not detecting per-machine.
You could use MSIGetProductInfo to find the installed products if the assignmenttype is “1” then you could set the below properties to Product Code of Per-Machine product
WIX_UPGRADE_DETECTED
OLDERVERSIONBEINGUPGRADED
Use a custom action on button click or schedule it after FindRelatedProducts.
This tells the installer of an existing version and installation is handle like an upgrade.
Windows Installer does not upgrade between per user and per machine, or vice versa. If you want this to happen you need to get in front of the install somehow and find out what type is already installed. Trying to do that when the product has been installed for another user (i.e. not the current installing user) is tricky. MsiEnumRelatedProuctsEx can be called a couple of times looking for per machine and per user installs to see what's going on. However there may be issues with you, User A, trying to uninstall a product that was installed per user by User B. If you are the same user it's easier. MsiEnumRelatedProductsEx can be called a couple of times to see if the product is per user or machine (in a launcher maybe) and you can uninstall the product before installing the new upgrade, or at least tell the user to do the uninstall. Anyway, it can be a mess, and the advice to stick with per machine installs is worth taking.
I should also point out that allowing per user AND per machine installs on the same machine is a feature, not a bug.

Automatic updating and upgrade management for Windows Installer XML (WiX)

I have been using InstallShield LE in Visual Studio 2010, but it is heavily limited and sometimes buggy. I looked at paid InstallShield versions, but these also have too many limitations for that price tag.
So I decided to switch to WiX. I have had some experience with it some years ago. It was pretty easy to build a simple installer using SharpDevelop with WiX tools.
Now I am trying to collect solutions and tools for WiX. Basically, I need to get the following functionality (requested by my client):
when I launch the installer, it should check a text file on the server and see if a newer version is available. If it's the case, then the installer should be able to download the updated installer package and launch it (are there any downloader utilities in WiX?)
solving dependencies. Major dependency of my app is .NET 4 (which itself depends on Windows Installer 3). The installer should offer the user to download and install them automatically
logging the installation process, also collecting the log file of the dependencies' installation process. I don't want the user to hunt various .log files in case .NET4 or WindowsInstaller3 installation fails. All the information should be collected in one place and if something fails, I should show the user a custom popup dialog with an option to save the complete install log file and send it to me
installer should be able to detect if there is a newer version of my app already installed, and show a meaningful customized error message before it exits
installer should be able to detect if there is an older version of my app already installed. and offer the user to exit installation or uninstall the previous version and install the new version. BTW, there are no minor component upgrades planned, I prefer to reinstall everything fresh (I guess, this is a major upgrade in the terms of WindowsInstaller). Installshield LE failed on me for this, it just showed an error box with the message about another product, but did not offer to uninstall it
in case of an upgrade, installer should be able to detect if some of application components are in use (running application processes) and show a custom error message and not just some cryptic "Installation failed"
I have read that it may be a bit painful to manage upgrades even if I keep my UpgradeCode intact, because this code is stored in the Windows Registry in a compressed way and also if the user renames the downloaded file, it might get detected as a completely new product by WindowsInstaller ... or maybe this is only the case with WindowsInstaller .msi files and WiX has some trick to avoid this issue?
About update downloading - I need this functionality also in my application itself. I am not sure how to implement it efficiently, so I can reuse the same update downloader code/utility in both WiX installer and in my app.
Is it possible to satisfy all these requirements using currently existing WiX tools, or maybe I'll need to code some components from scratch?
WiX is definitely the way to go in my opinion.
when I launch the installer, it should check a text file on the server and see if a newer version is available. If it's the case,
then the installer should be able to download the updated installer
package and launch it (are there any downloader utilities in WiX?)
In my opinion, this type of functionality is best handled by the application. However you can implement such functionality in a custom bootstrapper. The latest development of WiX includes a bootstrapper engine Burn that allows you to write your own custom bootstrapper on top of it.
solving dependencies. Major dependency of my app is .NET 4 (which itself depends on Windows Installer 3). The installer should offer
the user to download and install them automatically
You can use the standard WiX bootstrapper to install .NET as a prereq. Or if you create your own custom managed bootstrapper application, you can install .NET a prereq to your bootstrapper as in this example
logging the installation process, also collecting the log file of the dependencies' installation process. I don't want the user to
hunt various .log files in case .NET4 or WindowsInstaller3
installation fails. All the information should be collected in one
place and if something fails, I should show the user a custom popup
dialog with an option to save the complete install log file and send
it to me
Using the two bootstrapping methods above, when you launch your msi you can specify parameters for logging. In my own custom managed bootstrapper I created a button to open the log files created during installation.
installer should be able to detect if there is a newer version of my app already installed, and show a meaningful customized error
message before it exits
You can do this using launch conditions
installer should be able to detect if there is an older version of my app already installed. and offer the user to exit installation or
uninstall the previous version and install the new version. BTW,
there are no minor component upgrades planned, I prefer to reinstall
everything fresh (I guess, this is a major upgrade in the terms of
WindowsInstaller). Installshield LE failed on me for this, it just
showed an error box with the message about another product, but did
not offer to uninstall it
In my experience this major upgrades are the least complicated
approach.
in case of an upgrade, installer should be able to detect if some of
application components are in use (running application processes) and
show a custom error message and not just some cryptic "Installation
failed"
I think WiX/Windows Installer are generally good at handling these
scenarios and automatically notifying the user that
files/applications need shutdown without you having to author
anything extra in your installer.
All that said, you may want to look into creating your own custom managed bootstrapper using WiX and Burn. That is not trivial however. The best place to go is to download the source code to the WiX Weekly Releases and checkout the project src\Setup\WixBA. It is the custom BA that they wrote to install WiX. There isn't much documentation out there yet because WiX 3.6 is not released (although it is pretty stable). However you don't have to create your own BA to make a solid WiX installer that can handle upgrades and logging.