Automatic updating and upgrade management for Windows Installer XML (WiX) - 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.

Related

Check for Online Update in WIX

I work on WIX installer, I want the auto-update system that ClickOnce provide. I upload the new version on server and the end client can check online to see if there is a newer version available.
Can WIX do this?
Thanks.
You need to write something yourself to check for updates and download the new installer. Once you have the new installer, WiX can handle upgrading the version installed on the end user machine. Typically people have a secondary executable embedded within the main program which is responsible for launching the downloaded installer, so that the main program can close during the update process.
In the past, I've handled checking for and downloading updates with NAppUpdate, which is easily extensible for however you want it to behave. I'm sure there are plenty of other open source alternatives to handle this as well.
Wix does not have the capability to do so.
You can read the diffrences between ClickOnce and Wix (Windows installer) from:
https://msdn.microsoft.com/en-us/library/ms973805.aspx
I think you can wrap MSI in ClickOnce and use both.
Also you have Squirrel (Like clickonce) that is based on PowerShell but may not work on all target machines.

How to call a custom action from a UI in Wix

I am trying to add a delay to an installer. The reason for this is the installer must run a third party driver, but windows does not give "the device is ready to use" notification in time.
This leads to issues for the software as the version to be installed is determined by the device the driver is used for.
What I would like to do is generate a UI that will count down from say 10 to 1 before allowing the user to then proceed.
I have searched through documentation but haven't found anything in Wix that is capable of dong this.
Is this possible in Wix or how can I implement this?
The general answer is that you do a publish event from the dialog, as in this tutorial:
http://wix.tramontana.co.hu/tutorial/events-and-actions/control-your-controls
It sounds like this driver package is a prerequisite to installing your MSI. Therefore I'd create a burn bootstrapper bundle to install it before installing your MSI. I'd have to know more about this package but I suspect the thing to do is create a custom EXE to encapsulate the process and then wait up to 10 seconds while confirming the package is fully committed. Then it can return and burn will carry on to your MSI installation.
You shouldn't be installing drivers (or making any configuration changes to the machine) during the UI phase of your MSI.

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

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.

Forcing WiX Burn bootstrapper to allow MSI files to use REINSTALLMODE=amus

Since I wasn't a part of my company when our build process was designed and implemented (and has been successful for quite a few years now), I found out that there were things that were being done that may be looked at as 'hacks' to MSI 'purists'. However, in order to get a workable installer with Visual Studio 2012, I've been doing the best I can to mimic what was being done with the .vdproj files in Visual Studio 2010. Of the many snags I've hit, this one seems to be the last one that I can't resolve.
As part of our build process with Visual Studio 2010, we built our code and created a Framework MSI on one VM. Then we took that Framework MSI and installed it on a different VM. After the framework had been installed, we built our product code and created a Product MSI off of it. This created a Product dependence on our Framework. What this meant was that when installing on a client machine, the bootstrapper needed to install the Framework first followed by the Product. On uninstall our documentation stated to either have it handled through ARP or by command line 'msiexec /x {Product.msi/#ProductCode}' and then the 'msiexec /x {Framework.msi/#ProductCode}'.
At the time, management determined that the ProductCode would be the easiest way for other product teams to determine if our product had been installed on a machine. This lead them to the decision that they needed to keep a static ProductCode for both the Framework and the Product.
In order to handle upgrades, they had to create a ProductTool.exe that was nothing more than the msiexec wrapped in an executable that took a /ProductCode={#ProductCode} argument.
As part of our bootstrapper, they called:
Install prerequisites (Windows Installer 4.5, .NET 3.5 SP1, SQL Server 2008 R2 Express, Sync 2.1)
ProductTool.exe (Product.msi -- to uninstall the Product.msi)
ProductTool.exe (Framework.msi -- to uninstall the Framework.msi)
Install Framework.msi
Install Product.msi
However, I didn't discover until just recently that the Burn bootstrapper does not allow REINSTALLMODE=amus. In the install logs, it says that it changes it to REINSTALLMODE=vomus. Apparently in order to get that aforementioned process to work on upgrades, they had to set REINSTALLMODE=amus.
UPDATE: I finally got to talk to the original developer of the installer and found out that REINSTALLMODE=amus was used intentionally to revert all of the versioned files (assemblies, DLL files, etc.) and non-versioned files (.config, SQL script, etc.) as a risk minimization and robustness/"self-healing" strategy.
Having said all of that, is it even possible with a standard burn bootstrap application (BA) to set REINSTALLMODE=amus so that I can get the upgrades working? The MSI files have the Property's set, but Burn seems to override it.
No, this is not supported by the Burn engine today. Burn controls the REINSTALLMODE very carefully to correctly handle upgrades and repairs. Using a in REINSTALLMODE is far from a best practice and thus is not supported. Also, it isn't clear why a is necessary in the scenario you described.

Windows Installer XML (WiX) template or guidelines for deploying Petrel plugins?

Are there are any templates or guidelines for creating a Windows Installer XML (WiX) project for deploying a Petrel plugin?
Are there any reasons for WiX not having been selected as the natural successor to the old *.vdproj/MSI recommendation?
Has anyone tried WiX for Petrel plugins? I'm interested in exchanging ideas and experiences. I'm new to WiX, and find it difficult to get started.
(Off topic: the "new" PIP paradigm is lean and simple, but is a bad fit for enterprise use, where clients expect to be able to repackage an MSI in order to facilitate mass deployment through e.g. group policies. I'll post another question on this.)
MSI deployment is still supported in Ocean/Petrel regardless of the way of MSIs generation (and WiX is just another way to generate them).
In Ocean/Petrel 2012.1 you need to define custom action calling command-line tool PluginManager.exe with /install and /uninstall switch during the installation and uninstallation steps respectively. Custom actions are defined using <CustomAction> tags in WiX. There are two tricks you need to keep in mind when calling PluginManager.exe from MSI custom actions:
you need to supply your MSI installer ID (usually GUID) in /installerId:your_installer_id command-line switch during the installation. This will enable automatic MSI uninstallation of your plug-ins when Petrel is uninstalled
you need to run PluginManager.exe with /runFromInstaller switch during the uninstallation. By doing this you let PluginManager know that you run it from MSI installer, and so there is no need to run MSI uninstallation once more
You can find these and other tips and tricks, with full PluginManager.exe command line speicifications in the Plug-in Identity and Deployment White Paper in Ocean.chm (section "How to use PluginManager.exe in MSI installer").
Important information with Petrel 2013:
We have plugins that can be installed or uninstalled using MSI, created with Wix. When installing a PIP with PluginManager.exe without using the argument /installerId:<msi_installer_id> uninstalling the plugin using the Petrel physically deletes all your files, but create an inconsistency in windows uninstaller plugin. If we use the argument /installerId:<msi_installer_id> uninstalling the plugin using the Petrel occurs only logical deleting the plugin, keeping it physically in their original directory. This allows it to be installed subsequently also by Petrel. In the latter case, there is no inconsistency, because the windows uninstall the plugin and be able to delete all your files.
The problem is that uninstalling the plugin using the Petrel 2013 is not calling its MSI uninstaller. It should not be? This looks like a bug.