I am having an MSI file which copies a set of dll from it source to destination folder. While running the MSI the dll are copied to the destination folder also the MSI is installed in the system. I can see that in ADD or REMOVE programs.
Whenever there is a change in dll, i copying the new dll and building the MSI again. When i tries to run MSI in the same system i am getting error "Another version is already. Uninstall that version and proceed" something like that.
What i am doing until now is uninstalling the old one (MSI) and installing the new one.
But i want the MSI to update the older dll with the latest dll from the MSI instead of uninstalling and installing again.
Thanks in advance.
You can't just rerun the MSI to do an update. There's some background here, even if you are not using Visual Studio setups, and it's still relevant after all this time:
https://www.simple-talk.com/dotnet/visual-studio/updates-to-setup-projects/
To replace a single file, build a patch, an msp file. To upgrade the entire setup, including that Dll then use the WiX majorupgrade element, and that may be a lot easier than building a patch, especially if your setup is small and doesn't take long to install. Increase the file version of the Dll to make sure it gets replaced.
welcome to StackOverflow - it seems to be your first post. I would read this thread if I were you to get an overview of how to implement a WIX major upgrade: How to implement WiX installer upgrade?. Here is another thread (didn't read this one through): How to get WiX major upgrade working?
A major upgrade is essentially an automatic uninstall of the existing version and reinstall of a new version. This is the least error prone update mechanism in Windows Installer. It is the recommended approach to try at first - it works well. A minor upgrade - which is upgrading the existing install, is generally more difficult to get right in the beginning. A number of technical restrictions apply. Here is a very good summary of what is required for a minor upgrade to work (as well as other details): http://www.installsite.org/pages/en/msi/updates.htm
Check out this well known wix tutorial for upgrades and patches. And MSDN.
Related
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.
We have developed an application that is distributed through Windows Installer, created with the use of WiX, where our customers can upgrade from any older version to the newest.
Our latest version however, deletes 2 dll's, and this is only rectified through a reinstall.
Details on the NuGet packages
Microsoft.IdentityModel.Protocol.Extensions was upgraded from Nuget Version 1.0.2.206221351 and File version 1.0.20622.1351 to Nuget version 1.0.4.403061554 and File version 1.0.4.54.
Similar changes happened to file versioning of System.IdentityModel.Tokens.Jwt from Nuget version 4.0.2.206221351 to Nuget version 4.0.4.403061554.
So by changing how the File version was calculated, MS effectively changed the version to a downgrade of the previous (from 20622 to 4 on the build version).
Why the dll's are removed on upgrade
Some call it a bug, and some call it a feature, but what happens, is that the MSI has a step where it records all the files that needs to be upgraded, it then uninstalls the current version, and then only installs the files that was unchanged or bumped in version - any downgrades are left out.
Question: How do we get around it?
We are shipping this product to a lot of different customers, with very varied technical skills, so an upgrade better work, or we will be flooded with support issues. Are there anything I can change, without actually disabling features like the ability for the MSI to rollback in case of errors, which I have seen as a trade off for others solving the same issue.
You have a few options. One is to change where you schedule RemoveExistingProducts. Another is to use REINSTALLMODE=AMUS instead of the default OMUS. Another is to do version lying on the offending DLLs so that they always get reinstalled. (Author the file element so the version is 65535.0.0.0 or something like that.)
It's an MSI feature... the bug is in Nuget releasing a newer DLL with a lower version #. That breaks MSI's component rules and default file versioning rules.
This might help:
https://blogs.msdn.microsoft.com/astebner/2015/11/16/why-windows-installer-removes-files-during-a-major-upgrade-if-they-go-backwards-in-version-numbers/
and basically Chris is correct, and:
The RemoveExistingProducts placement should be before the costing actions which cause the error.
Another alternative is to open the files with Visual Studio and alter the file versions in the resources so that the rules are followed. File version would not affect assembly version. Just run Visual Studio, then File-Open File, and the Resources section will show where you can change the version.
It's also very likely that a repair will restore the missing files because the missing files "break" the product install. That's easy to test. If that is really the case, then it will repair automatically (and just once) if the app starts with a shortcut, or you can arrange for the shortcut to be advertised. If not, I've seen people use MsiProvideComponent () to make sure the files exist because that will do the repair/install.
Background
WiX & the Windows Installer are completely new to me.
In production, we used an MSI (created using WiX) to install our software. The MSI references a third-party assembly (e.g. OtherCompany.ThirdParty.dll, version 2.5).
The next release of our software must reference an older version of the third-party assembly (e.g. OtherCompany.ThirdParty.dll, version 1.7).
While I understand that installing an older version of a dependency is uncommon, it must happen.
So my question is... how do you configure a MSI (generated by WiX) to use an older version of an assembly without having to completely uninstall the existing package?
Options
We have explored the following:
Increment the assembly's version
it's a third party assembly, and
for traceability this is not an option
rename the assembly
the dependency is being retrieved using NuGet... so this won't be straight forward
force existing install to be completely removed (automatically or manually)
we don't want configuration information that was collected during the previous installation to be lost, so this isn't an option
schedule RemoveExistingProducts before costing
not recommended by Microsoft (see: MSDN)
custom action: to delete dependency
if the installation fails, the application may be left in an undefined state
override file version in setup
moving forward, this will be error prone
changing the REINSTALLMODE
From the articles that I have read, it appears that this should only be used as a last resort.
use a WIX companion file
am still investigating
For Moderators
I am aware that there are other SO posts on this subject. Please note that several of the recommended solutions are incomplete or are error prone.
References
MSDN: Patching and Upgrades
MSDN: RemoveExistingProducts Action
downgrade a library during a msi upgrade
Why Windows Installer removes files during a major upgrade if they go backwards in version numbers
MSI Writing Guidelines
What Every Developer Should Know About MSI Components
Windows installer deletes versioned file during product upgrade, instead of downgrading it
MSDN: Windows Installer - File Versioning Rules
Msiexec REINSTALL=ALL REINSTALLMODE=vamus not reinstalling anything
good overview of what is happening under-the-hood
Forcing an upgrade of a file that is modified during its initial installation
this is an older post is from 2009
Some issues are best solved by the application design rather the deployment.
There are two places to save a particular version of a .NET assembly: the GAC or the application folder (or subfolder with probing privatePath). In either case, you might want to use a bindingRedirect.
Also, you can load from a specific location using AppDomain.AssemblyResolve, provided the binding is not successful using the GAC.
General Reference: How the Runtime Locates Assemblies—thanks to #Pressacco.
I have an old installer that is made with InstallShield 2015, its non-MSI based (I tried opening it with 7zip and could not --> non-MSI based, am I right?).
In general, I need to stop using InstallShield and migrate to Wix.
Is it possible some how to convert InstallShield it to Wix?
Using Wix, I need to detect if a previous version (the InstallShield version) is currently installed and automatically uninstall it and then continue with the normal Wix process. Is such a thing possible?
Thank You :-)
I'll add a quick answer for reference, though the problem appears solved already.
If the old Installshield setup is an MSI, you can use dark.exe from the WiX toolkit to "disassemble" an MSI into WiX source code (dark.exe can also decompile WiX setup.exe bundles - there is a somewhat messy description of this here: How can I compare the content of two (or more) MSI files?).
After some cleanup you can compile the WiX source to a new WiX-built MSI. A bit of knowledge and experience is needed for the cleanup to be successful (eliminating GUI sections, add a WiX GUI, realign source paths, clean up binary stream tables, etc... - not trivial, but not rocket science :-).
If the old setup was a legacy installer (not MSI), you can convert it to MSI by using a repackager tool to capture changes done to the system during installation and convert them to an MSI. A lot of knowledge is required to clean up such a capture. If you know the product it is often better to code a new setup "by hand". Or if you are in a large corporation chances are you will have a "repackaging team" available somewhere who will have the expertise to do this job for you.
Yes, old setups can be uninstalled as part of your new MSI.
As you discovered if the old setup was an MSI you can simply use a major upgrade to remove it during the new WiX install.
If the old version was a legacy setup things can get considerably more involved often requiring you to "record" a dialog response file to feed to the uninstaller function of the old setup.exe file. Not at all trivial, and quite error prone. Incidentally one of the major benefits of MSI is the completely suppressible GUI.
For reference, here is an old answer with information on dealing with the infamous setup.exe files that we frequently have to uninstall and upgrade:
How can I use powershell to run through an installer? The setup.exe can be many different things: Installshield Setup, Advanced Installer Setup, Inno Setup, Self-Extracting Zip-Archive, a proprietary setup format, the list goes on...
My WiX installer (Wix 3.10, MSI 4.5) uses MajorUpgrade for updating. The files to be installed are harvested with heat.exe in pre-build. The current (older) msi file contains a file nlog.dll (which came with a NuGet package v4.1.0) that has a file version of 4.1.0.0, a product version of 4.1.0 and last write time of 2015-09-01.
Since the nlog team ran into some strong naming issues, they published an updated NuGet package v4.1.1, containing an updated nlog.dll with its file version decreased back to 4.0.0.0 while its product version has been increased to 4.1.1, last write time is 2015-09-14.
Now I'm running into a related issue as Robbie did here: wix major upgrade not installing all files: When I install the new msi package and the major upgrade is performed, the present nlog.dll (which is newer according to its file version, but older according to its file date and product version) is being removed, but the new nlog.dll isn't installed.
However, using Schedule="afterInstallExecute" or Schedule="afterInstallFinalize" as suggested won't do the trick for me. Instead of removing the newer file and not installing the older one as in Robbie's case, it doesn't overwrite the present file, and just leaves it in place.
Long story short, I would like my installer to simply install all files that come with it, regardless of any file/product/assembly versioning stuff. There are valid circumstances in which replacing a newer file with an older one is desired. Can't you just tell the installer engine to ignore file versions/dates? If not, what are my options?
You can set the REINSTALLMODE property to AMUS instead of OMUS. This will affect all components globally.
The other trick is to use "version lying". This is where you author the file element with a higher version. Using heat can make this difficult as now you have to transform the XML before compiling it.
Of course the real solution is to hit the nlog team over the head. But based on what I've seen from them over the years it'll never happen. Perhaps you just use a resource editor to hack the DLL and 'fix' the version #. That's assuming you don't need it strong named. This feels dirty and a possible CM nightmare to me though.
Or just dump nlog. :)
If this is a major upgrade and you want everything to be uninstalled before the new product is installed, then you schedule RemoveExistingProducts after InstallInitialize or InstallValidate. That does the uninstall first.
I can't tell if you're getting the "disallowing install..." issue or not, but if you are, and there are other clients of the Dll (it's shared with other installed products) then I'd see if that Dll has support for private copies so you can have you own private copy for your product. If it is shared with other products I wouldn't use version lying - I'd open the Dll with Visual Studio "open as file" and change the version! Make that your latest shared version, so every package that installs it can just use it.
If it's not shared with other products and you're just running into that MSI quirk, then make your own upgrade element and schedule RemoveExistingProducts before CostInitialize, which is what is deciding not to install. That works, but it's before MigrateFeatureStates so you will lose feature migration in your major upgrade.