How can I make sure a downgraded library is installed by my MSI? - wix

I have an MSI that setups my application. It has a single component and installs only to %PROGRAMFILES% (no shared binaries). Simplified, it looks like this
Msi file, Monday build:
Program.exe (v1.0.0)
ThirdPartyLibrary.dll (v2.0.1)
Now, if I discover a bug in the program caused by my upgrade of the ThirdPartyLibrary dll from v2.0.0 to v2.0.1, and thus revert the reference to v2.0.0, it seems my MSI doesn't automatically replace the file in the installation directory?
Msi file, Tuesday build:
Program.exe (v1.0.0)
ThirdPartyLibrary.dll (v2.0) <- downgraded
What is the best practice here to ensure that the program folder always contains exactly the binaries in my setup? Should I a) wipe everything from the setup directory before copying the new files? Is there an option (in Wix) I can use that makes the msi force an overwrite of all files regardless of version?
What if I remove a file from the setup (a file that would cause errors if present at runtime), then the only way to have a working program after the setup, would be if it deleted all files first?

You can use a msi trick. In the File table in the msi database edit the Version column and enter a higher version, 3.0 for example. This way you will take advantage of the file versioning rules.

Related

Overwrite pre-msi files in WiX

I have a WiX project making msi which replaces much older installation which was made by a set of scripts which unpacked zip files.
I'd like to specify that certain files in msi must force overwrite already existing non-versioned files from the old installation. Later it wouldn't be a pb as msi to msi update would be an upgrade.
Is it possible to specify on a per-file basis that msi must overwrite old non-msi installed files?
I will add some links for you and a summary.
Yes, you can overwrite single files by various means and you can even
force downgrade files setup-wide, but the latter is terribly dangerous
to do (information on dangers in section 4 here).
Ensure Overwrite: This answer describes various measures to always-overwrite files: Ensure file overwriting - with a WiX example. Here is an alternative answer.
The use of companion files is what I would recommend.
Hacking file versions I do myself sometimes - just to make things work.
I prefer to move or rename files to "remove the problem".
See the above links for more on the above "options".
Further information:
On file overwriting in general - step-by-step (describes the REINSTALLMODE property and the problems that are caused by using it to force-downgrading files during installation)

File of a new component isn't installed because there was an old component with the same file

We have a problem that a fie is not installed upon a major update
We have a major update with <MajorUpgrade Schedule="afterInstallInitialize"...
We an old component with 1 file (xyz.exe Version 12.34) from a external manufacturer
We have now a new file from a new manufacturer and with the same name (xyz.exe Version 2.34). The new file has a lower version number than the old one.
We created a new component in the install package and removed the old component (in fact we gave it a new guid)
Changing the name of the exe isn't possible, it would have to much influence upon documentation and internal functions.
On a normal installation everything is OK.
But what happens now on an update:
The installer starts.
And detects that the new component exists (xyz.exe) with a lower version, so it will not be installed.
the installer runs and removes the old component
But it doesn't install the new because it just detected that the component was already installed.
Doing a repair installation fixes the problem and the file is than again present.
Setting the KeyPath to the Component fixes the problem. But it seams wrong to me. The directory where this file is installed is the main installation directory.
How to force the installation of this component?
Similar Answer: How to Explicitly Remove dll During Majorupgrade Using Wix Toolset
Major Upgrade Downgrade: In order to overwrite binaries with higher version numbers on major upgrades there are a couple of preferred options:
The preferred approach would be to use a companion file (third party files).
Or if you can: compile a new binary with a higher version number (for your own files).
Companion Files: A snippet below on how to use companion files in WiX:
<..>
<Component Id="MyFile.exe" Feature="Main">
<File Id="MyFile.exe" Source="MyFile.exe"></File>
</Component>
<!-- Do not re-use any GUIDs in your own sources! (very important) -->
<Component Id="MyFile_2.exe" Guid="{00000000-0000-0000-0000-3D82EA2A99AF}" Feature="Main">
<File Source="MyFile_2.exe" CompanionFile="MyFile.exe"></File>
</Component>
<..>
One-Line Summary: In the second component we point to the first component's file so that MyFile_2.exe will install whenever MyFile.exe is installed - regardless of versioning issues.
Then there are a number of further options:
REINSTALLMODE: The MSI property REINSTALLMODE can be used - but it has a number of side-effects:
Setup 1: Version 1.0.0 for a setup:
msiexec.exe /i Setup1.msi /qn
Setup 2: Version 2.0.0 for the major upgrade setup:
msiexec.exe /i Setup2.msi REINSTALLMODE=amus /qn
Several Problems: There are several issues with REINSTALLMODE that makes it an unsafe feature to use (try emus instead? See documentation - a little less brute force maybe). It is a shame that this setting applies to all features in the setup - that makes it very dangerous:
can downgrade shared files system-wide - if there are merge modules included - for example (features in Windows are in place to prevent most of this problem: WFP and WRP in Vista an beyond - non-Microsoft merge modules can still cause problems for non-Microsoft shared files)
can cause inconsistent version estate since an old package can be installed after a newer one and downgrade only some of the shared files
can downgrade or wipe-out settings in non-versioned files and registry settings (note to self: test this again, there are complexities with component settings)
can cause a significant increase in the number of requested reboots due to attempts to needlessly replace in-use files of the same version (the real fix for this is to shut down services properly and to use the restart manager to allow applications to be shut down automatically during deployment - on file locks).
there are several further issues that are quite specific
Hack Binary Version: An ugly, but effective option is to change the version of the actual binary file using Visual Studio to set a higher version number (you open the binary as a resource and set a new version - this is obviously very different from compiling a new version of the binary using visual studio source code compilation). There are several side effects:
you break digital signatures
you can create "version confusion"
there are risks involved writing a new binary from Visual Studio
it is a "hack manual step" - you might need to keep doing this for new versions?
etc...
Move, Rename: If you can de-couple the new file from the old by renaming it or moving it you can work around the problem. If you get a new version again for the future, you might have to do this again. Clunky.
"Load From": Putting the file somewhere shared and load it from that specific location and removing the old copy from your installation folder. Could that work? This means the file could also be delivered by another setup at that location.
Version Lying: In Installshield there is a concept of being able to set a specific version number to a file. I am not sure how to implement that in WiX. There is also an "always overwrite option" that apparently sets a maximum value for the version so the existing file is always overwritten.
Some Links:
Why Windows Installer removes files during a major upgrade if they go backwards in version numbers
"Downgraded" MS dll disappears on upgrade - Windows Installer
Install a file regardless of version number with WiX
How to make better use of MSI files
The opposite side of it: file preservation and file overwrite rules.

MSI Reinstall Issue with Specified Account already Exists error

We have 2 installer sources in WiX to create installer for a single product with same Product Version, GUID and Package GUID also.
Those 2 installer projects will yield different outputs, one output being just a single MSI file (File1.msi) and other project output is a CD-ROM structure having different MSI file name (File2.msi).
So now issue arises when we installed the product using single MSI file, upon that if we invoke MSI from the other CD-ROM output, we end up getting below mentioned error.
I tried keeping same MSI filename for both kind of installer output, then this above error dialog was resolved but repair functionality isn't working.
If some files were deleted in the product's destination folder, it says source file not found error pointing to CD-ROM installer source folder.
Please help where I'm going wrong. I want to support Repair installation without this errors.
The dialog is expected. You can't change the name of the MSI except during major upgrades.
After that, if you rebuilt to create the different layouts, each MSI probably has a unique PackageCode and that makes them unique packages. That is most likely why repair isn't working. A verbose log file should tell all.
Updated: Compile your main MSI, then run administrative image on it and put the extracted files and MSI on the CD? Put the compressed
version on there as well - just in case they prefer that kind of
release (happens).
I am not sure what will happen when you run both setups this way, but
I think the MSI flagged as an administrative image extract might be
detected by the engine. I am not sure. Should work. Built-in approach for MSI, and you are not fighting wind-mills.
User Accounts: Are you creating any NT User Accounts? Did you set the FailIfExists attribute to yes? Please check here:
User Element (Util Extension). What is the setting for UpdateIfExists? (if any).
Other Issues: There might be other issues as well as Rob mentions. You can not use the same package code for both release types because a package code by definition identifies a unique file. All kinds of X-Files-like problems occur if you try to "hack" this. Not a fight you want to take on.
Administrative Installation: Why would you want to distribute different setups on CDs these days? Corporations that use your setup will run an administrative installation on your setup extracting all files - which is a much better concept. It is essentially a glorified file-extraction, and it is a built in Windows Installer concept intended to make a network installation point for software - among other things. It essentially extracts all files and translates the Media table to use external source files.
List of Links:
What is the purpose of administrative installation initiated using msiexec /a?
Extract MSI from EXE

How does Wix decide to install a particular file?

As I put in title, the question is how does Wix decide to install a particular file?
So I have exe file and when I change something in exe file and rebuild it, it will not get reinstalled if I don't change version. But if I change something in resource file, resource file will be replaced even if I don't change version of my application. So how wix is deciding if he need to replace file during upgrade or not.
I am using wix3.9. MajorUpgrade is schedule afterInstallFinalize.
Versioned files get replaced based on file version, yes, but data files get replaced based on whether you have specified file hash or not. I think WiX generates file hases by default, so this is the overwrite rule:
https://msdn.microsoft.com/en-us/library/aa370532(v=vs.85).aspx
and it's a Windows Installer rule that applies to all MSI settup, not a WiX decision.
P.S. afterInstallFinalize isn't an ideal place. afterInstallExecute is safer, and it will have the same overall result. The issue is that after InstallFinalize means that the new product is installed. If the uninstall of the older product then fails and rolls back you will end up with both old and new products installed, otherwise known as a mess. afterInstallExecute makes everything part of the transaction so you get the original product installed if there is a failure to uninstall it.

Always update files in minor upgrade (how to)

I am creating an install package using InstallShield Pro X. The upgrade works properly. However, the product manager wants the upgrade to replace all files on an upgrade even if the create date != modify date on the file.
I see that to do this I need to set REINSTALLMODE=vamus rather than vomus. However, I don't see how to tell InstallShield that I want it to use that setting. By default setup.exe always passes vomus to windows installer.
There is a property in the InstallShield project named ReinstallModeText that I changed from omus to amus but that seemed to have no effect.
So, how what do I set in the install project so that when setup.exe detects to run an upgrade it sends REINSTALLMODE=vamus? Thanks.
Update: Tried adding the following to the MSI Command Line value in the Release section:
REINSTALLMODE=vamus
This did not work. Setup.exe didn't set REINSTALL=ALL on the command line what I did this. I added that to the MSI Command line and the upgrade worked as expected. But, not the problem is if it is a NEW install those properties are still being set and the installer fails.
In investigating this further and testing more options I think the best answer is to modify the product code in addition to the product version and author it as a major upgrade which removes the previous version first and then installs the new files.
The main problem with this is that it takes alot longer for the installer to run. I also think that you can not issue this as a patch, but I could be wrong on that count.
Don't set the REINSTALLMODE to amus or vamus (force overwrite files). These settings apply to all components in the MSI, and could hence in theory downgrade system files or at least shared files - this typically involves files included via merge modules. It is normally safe to set REINSTALLMODE to emus (replace files with lower or equal version number). Even this can trigger a file replacement error if you try to overwrite a system protected file on newer versions of Windows featuring Windows Resource Protection (wikipedia) (Windows Server 2008 and Vista onwards). On older Windows versions the file would likely be overwritten and then restored in its right version from the dllcache via the Windows File Protection feature provided that feature had a good day. There was (and is) an associated tool for system file checking: System File Checker.
If you have issues with files that should be replaced even if they have been edited, you can use the RemoveFile table to schedule the file for removal during install (and then it will be reinstalled).
The real solution is to consider the installation folder in %ProgramFiles% as read only, and not have the application save ANY settings or change any files. All config files should go to the user profile or the alluser profile and the application EXE file should be responsible for the copy to the profile locations.
See my answer here.
I don't have IS X handy, but in later versions of InstallShield you would go to "Releases", highlight your release, go to the "Setup.exe" section and there's a field called "MSI Command Line Arguments". There you would indicate any command-line arguments that you want Setup.exe to pass to Windows Installer. E.g. REINSTALLMODE=vamus
You mentioned you used ReinstallModeText with "amus". Have you tried ReinstallModeText equal to "vamus". The "v" causes the installer to run off the source package, not the cached package, and that may be your problem.