I have a Wix project that I have set to allow major upgrades. I'm using WixUI_Advanced for a choice between per-user and per-machine installs. When I install and upgrade per-user everything works as expected, the installer recognizes an upgrade and there is only one entry in Programs and Features. However when I choose a per-machine install, it starts duplicating entries in Programs and Features (even when both install and upgrade are per-machine and to the same folder).
Looking at the install log file it seems that FindRelatedProducts is executing before the user gets a chance to select a per-machine install, so the installer thinks that the context has changed and won't do an upgrade. I attempted to suppress FindRelatedProducts in InstallUISequence but when I do that the installer still skips FindRelatedProducts in the InstallExecuteSequence.
What are my options at this point?
You could manually execute the FindRelatedProducts action again, after the installation context was selected. Use the MsiDoAction method. I used this approach once and it seemed to work.
A better approach would be to run your own custom action before FindRelatedProducts that would search for a previous version of the product already installed. That custom action should set ALLUSERS to either 1 or to Nothing depending on the scope of that previous version, so that FindRelatedProducts finds it and schedules its upgrade. A good idea would then be to disallow selecting the per-user scope for the user if the previous version was installed per-machine - otherwise the installer may have insufficient privileges to upgrade the previous per-machine installation.
This seems to be the approach taken by InstallShield. If you create an empty test MSI package with the free InstallShield Limited Edition and then de-compile it with Dark, you will see that that custom action is called IsSetAllUsers and located in SetAllUsers.dll.
Related
i am trying to Upgrade MSI from Per-Machine to Per-User.. but its not working.
After Upgrade it shows twice on Control panel and twice shortcut on the desktop means its unable to uninstall pervious one.
and it able to Upgrade Per-Machine to Per-machine and Per-User to Per-User but unable to upgrade Per-Machine to Per-user
New Build Code
OLD BUILD CODE
This is because the major upgrade does not work across installation contexts (what WiX calls installScope). Thus the previous version is not being uninstalled. The second note on Major Upgrades says this:
Note If an application is installed in the per-user installation context, any major upgrade to the application must also be performed using the per-user context. If an application is installed in the per-machine installation context, any major upgrade to the application must also be performed using the per-machine context. The Windows Installer will not install major upgrades across installation context.
Let's say that I have distributed a WiX Burn package with a certain upgrade code (I do not know any product codes). Let's say that I decide that moving forward, I want to move to an MSI package. The question is: how can I remove the previous Burn package given the upgrade code when I install the MSI package? I have given both the same Upgrade Code, but the MSI appears not to uninstall Burn by default.
You'd likely need to write a custom action in your MSI that walked through all registry keys under:
HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
and searched for a registry value "BundleUpgradeCode" with the value of your static UpgradeCode guid. When you find it, read in the value of the entry "UninstallString" or "QuietUninstallString". That's the command you'll need to execute in order to uninstall the previous bundle before installing your new MSI.
Caveat: there's no rollback support with this approach if you uninstall the old bundle and the new MSI installer fails. You'll end up with a machine that has neither of your products installed.
In one installer version of our product, I've added a custom dialog (shown by a CA using session.Message()) that asks the user if he wants to keep some of his data, at uninstall.
The CA has the condition set to REMOVE="ALL" AND NOT WIX_UPGRADE_DETECTED.
The dialog is correctly shown when doing a normal uninstall, but it also appears when removing the existing product, at a major upgrade. At that point, the installer hangs and it can only be closed from the Task Manager, resulting in an incorrect upgrade.
The installer version, containing the issue, has already been shipped.
Is there something that we can include in the next installer version (that does a major upgrade), that solves the dialog issue when removing the existing product?
The property UPGRADINGPRODUCTCODE is set in the older product as it is being uninstalled. WIX_UPGRADE_DETECTED is set in the incoming new upgrade setup when it detects.
A condition of REMOVE="ALL" AND NOT UPGRADINGPRODUCTCODE seems to be what you want, showing the dialog during unstall but not when the uninstall is because of a major upgrade.
You need to fix the cached MSI of the original version. There shouldn't be any UI during a silent installation transaction. You'll need to make a copy of the original built MSI, modify it to not execute that custom action and then recache it using msiexec /I foo.msi REINSTALL=ALL REINSTALLMODE=vomus before you can do your major uprade. Or, tell your users to do an uninstall first. This is the reason you are supposed to test your servicing strategy before you go to production. MSI is like an airplane... there is not stop or go back button. You are always moving forward and you have to plan accordingly.
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.
I'd like to create a standalone silent uninstaller using WIX that I can send to specific people for support purposes that can be double-clicked to execute the uninstall of our product when the uninstaller did not work properly on their machine and no longer exists (some users remove things manually using other tools). I have a .wxs file that uses the same product id and package id of the previously installed program, and if I run from msiexec /x it uninstalls the previously installed product perfectly. Double-clicking on it (which is all these users can be expected to do) however runs installation, not the uninstall. I tried adding
<Property Id="REMOVE" Value="ALL"/>
<Property Id="ACTION" Value="UNINSTALL"/>
and making sure all InstallExecuteSequence actions are not using an "Installed" check but the product is still installed after running successfully, the log file shows it is still executing ACTION INSTALL:
MSI (c) (A8:F8) [15:42:08:324]: PROPERTY CHANGE: Adding ACTION property. Its value is 'INSTALL'.
MSI (c) (A8:F8) [15:42:08:324]: Doing action: INSTALL
MSI (c) (A8:F8) [15:42:08:324]: Note: 1: 2205 2: 3: ActionText
Action 15:42:08: INSTALL.
Action start 15:42:08: INSTALL.
Is there a way to force an .msi file to perform an uninstall without using the command line or add/remove programs entries? I've seen entries about using ARPSYSTEMCOMPONENT but not enough information to do it.
I don't think so. You could, of course, use an exe to do it. I would also strongly suggest that you use the original msi file instead of creating a different msi with the same product code.
For the exe, you could use any number of chainer/bundler/downloaders. There is NSIS and also WiX's own Bootstrapper, ... even WinZip.
You should also note that many package management systems that run uninstall commands will run the install command first if anything is amiss. The theory is that an uninstaller can't properly run unless the critical data placed by installation exists. (E.G., WPKG). For Windows Installer, this usually doesn't apply since it's data is hidden from the user. But if they found it and corrupted it, reinstalling and/or repairing using a fresh copy of the original msi might do the job.