MSI Reference Counting: Two products install the same MSIs - wix

When products A and B each install several MSIs and some of the MSIs are the same, will uninstalling either A or B affect the other? Does install location matter?
Also, what happens when common MSI C's version is higher in Product B and B upgrades C on install? Now uninstalling B will remove the common MSI C which breaks Product A. How do you handle this gracefully without using the Permanent flag?

The first thing that comes to mind with this question is whether the products in question are decomposed the way they should be.
As a general rule all MSI files think they own whatever they install, and they will uninstall everything attached to a component GUID inside the MSI on uninstall if the reference count (number of products using the component) is zero.
There are some qualifications to this rule:
If the component is marked permanent it is never uninstalled
If the file / registry item has no component GUID at all, it is installed, never tracked by Windows Installer, and won't get uninstalled either
Finally the reference counting for MSI allows the same component to be shared between several products and it will persist on disk during uninstall if it is registered in use by several other installer packages
The mechanisms for creating shared components between MSI packages are generally:
Merge modules allow you to install shared components that are reference counted and that will remain on disk after uninstall of a related product if there are other clients using the GUID on the system. A merge module is merged into other MSI packages at compile time. A form of binary early binding if you like. It can be merged into any package.
With the advent of Wix (xml based installer source files), it is possible to include the same segment of files from several setups via an XML source include file instead of a merge module. This is vastly superior in my opinion due to the fact that Wix works better for source control (see Wix link for explanation). It is crucially important to realize that a "Wix source include file" has the exact same effect as a merge module - its components are reference counted properly for sharing between different installer packages, provided the GUIDs in the source file are hard coded (I recommend not to use auto-generated guids for this particular purpose). It is my personal opinion that you should use third party merge modules for generic runtime files, but only Wix includes for your own shared files. Merge modules are harder to manage than Wix includes imho.
Updating and file replacement:
As to update scenarios the MSI file replacement rules will take care of updating newer files, dependent upon the overall setting in the special Windows Installer property REINSTALLMODE.
In general higher version files overwrite lower version files. Non-versioned files are overwritten if they are unmodified. If they are modified the create and modified date stamps are different and the file is left alone.
Keep in mind that the issue of downgrading files is actively discouraged by the overall MSI design. If you need to downgrade files (shared or not), there is something deployment smelly about your design.
At this point I would thoroughly read these answers:
Windows Installer and the creation of WiX - for a short Wix history and context
Change my component GUID in wix? - for component reference counting
Wix installation, server, client or both - for client / server packaging
Wix to Install multiple Applications - for changing requirements and setup problems
WiX tricks and tips - for community Wix tips and tricks
How to include wxi file into wxs? - for a simple idea of how to deal with Wix include files
Provided you use Wix, or you are willing to use Wix, I would think the best way to deal with your overlapping products would be to decompose your installer into Wix segment source files that you include as needed in your main installers. This will allow the uninstall of one product to leave in place any components used by other applications.
With that being said, I do not like to cause too many overlapping dependencies in my installers for the reasons listed in this article (also listed above): Wix to Install multiple Applications .
For stability it is crucially important that shared components are stable before being used by too many setups as a bug fix as a general rule will require the recompilation of all setups the shared component is compiled or merged into. The easy way to say it: bundle files together that change together.
To counteract this need for massive recompilation, you can chose to deliver a stand-alone supporting setup consisting of some of the shared components. One, or a couple of such "shared components setups" that are likely to contain Wix includes that change together on a similar, slow release schedule, and then separate setups for each product should be able to account for any deployment need whilst maintaining a balance between maintainability and flexibility.
The product setup should then be the one that gets recompiled often, and the shared modules setups should be designed for minimal recompilation. Then wait for changing requirements :-).
To me it is all about cohesion and coupling, and the difficulty of balancing sales, marketing and technical needs.

If Product A and Product B has a MSI C in common then
If Product A is installed, also MSI C is installed, now when Product B is installed MSI C will not be installed since its already available in the system (if Product B is WiX Burn based, it registers a dependency). In case of uninstallation reference counting is automatically handled if Product A and Product B is WiX Burn based installer or any other Bootstrapper which supports reference counting else MSI C is removed along with Product B.

even I was looking for the answer of the above question, but in Wix v3.7 and higher, the MSI packages are automatically reference counted by the Burn engine. I have tested this, and works perfect.
The same can be checked in Rob's blog

Related

How to express a file dependency using WiX

I have a couple of MSI files installing different applications. All these packages share the same underlying runtime which basically is a set of DLLs. This runtime is pulled in each of the installers as a merge module. Installing a couple of these packages works just fine, always the latest version of the runtime stays on the system and when the last package is removed everything is removed from the system.
Now I had to split one of the DLLs into 2 and added a new component to the runtime installing the new DLL. This new DLL is linked with other libs of the runtime. Now assume the following scenario:
install an old package with the merge module for the runtime without the new DLL
install a new different package with a newer version of the merge module for the runtime. Now there are 2 packages on the system
remove the new package again
Now the old package is broken because:
the new component for the new DLL had a reference count of one as the old package didn't have it and therefore gets removed
the other runtime DLLs stay on the system because they are still referenced by the older package. However as they are new they are already linked with the new DLL that is now no longer present
So my question is:
Is there either a way to explicitly state in the WiX code that file A depends on file B so that it stays on the system until all references have been uninstalled?
or is there a way to explicitly downgrade the dependees in a way the dependency does not longer exists?
Am I doing something fundamentally wrong?
What I did try on a clean machine was to follow Stein Åsmul suggestion like this:
<Component Id='OldLibsNowDependingOnNewLib' Guid='C8DCD2AB-CBE5-4853-9B25-9D6FE1F678DD'>
<File Id='LibOne' Name='LibOne.dll' Source='$(var.SourceDir)/LibOne.dll' />
<File Id='LibTwo' Name='LibTwo.dll' Source='$(var.SourceDir)/LibTwo.dll' />
</Component>
<Component Id='NewLibComponent' Guid='CD2DB93D-1952-4788-A537-CE5FFDE5F0C8' Shared='yes'>
<File Id='LibNew' Name='LibNew.dll' Source='$(var.SourceDir)/LibNew.dll' />
</Component>
However unfortunately this doesn't change the behaviour.
UPDATE: Looking in the SDK again, I see the flag msidbComponentAttributesShared for components. This
looks promising for the problem you describe. Please try to enable
this flag and recompile the version 2 of your setup (unless it is
live).
Enable the Shared flag for the component in question (last part):
<Component Feature="Product" Shared="yes">
This seems to be for patch support, but maybe it will work for your case too. From the MSI SDK:
"If a component is marked with this attribute value in at least one package installed on the system, the installer treats the component as marked in all packages. If a package that shares the marked component is uninstalled, Windows Installer 4.5 can continue to share the highest version of the component on the system, even if that highest version was installed by the package that is being uninstalled."
I think the above should work, but don't have time to test right now. Leaving the below for review.
Short Answer: Use WiX's Burn (setup chainer) to install in sequence the application setup and a new, separate runtime setup that can be handled
independently of your application setup versions.
Prerequisite Setup: Interesting case. This is why I like to split prerequisites into its own MSI package and deploy it via a Burn Bundle Bootstrapper. Burn is WiX's bootstrapper / downloader / chainer - essentially a way to run several setups in sequence - in a few different formats such as MSI, EXE, MSU, MSP. When doing this - putting the runtime in its own MSI - there are no entanglements and you get good decoupling of your runtime and application-specific files. In other words: you can update the runtime files on its own - with their own MSI. The files will even have a reference count of 1 meaning you can easily uninstall them all (not if you install via a merge module that also can be included in other packages - more below).
Merge Modules - Semi-Static Linking?: In a weird way merge modules are sort of semi-static linking. The whole merge module is a version - a binary bundle (think COM) - but its installation behavior is one of "higher version wins" only. Hence a single newer MSI with the newest merge module in it will update the shared files for all applications that use them. Uninstalling will then do what you see: preserve the files that were originally installed by older setups.
Options: One "solution" in your case could be to re-compile the older setup with the newer merge module and then reistall, which I understand you don't like. I don't like it either. I guess it is no solution at all. Some other suggestions:
Permanent component: You can set the hosting component for the new file to be permanent on the system. This is very easy, but also quite silly and not always very desirable. Uninstall will then not remove the file at all.
Prerequisite: This is my favorite option mentioned above. You compile a prerequisite MSI setup that installs the runtime components. This MSI can deliver updates to itself without affecting the main application. This is the primary benefit I am after: Cohesion & Coupling benefits.
Merge Modules: I would avoid merge modules altogether, but it is common to merge the same merge module into the prerequisite setup - if you have a merge module already.
In most cases merging a merge module is fine since you then install the prerequisite and then you can install and uninstall application versions at will without affecting the runtime since a different product (prerequisite MSI) installed the runtime - and that setup should stay behind and not be uninstalled.
If the merge module does not work and brings along the conflict that you already had, maybe try to combine with the msidbComponentAttributesShared "solution" mentioned above. Not tested by me so far. Always risky to suggest things like this, but it is "best effort".
WiX Include Files: I prefer to use WiX include files which allows me to pull in new files without re-authoring a whole merge module in binary format (think C++ include files as opposed to a merge module's COM-style binary reuse).
Side-By-Side: Many people prefer to install prerequisites side-by-side so that several versions of the runtime can co-exist. This may or may not involve the GAC. Switching runtime versions would then be a manifest-manipulation task. Generally somewhat confusing, but doable. You can use both merge modules and separate MSI files to deploy such runtimes - as described above. I would definitely use a prerequisite MSI.
I can't think of more right now, but I know I have forgotten something important this time. Let me persist what I have for now in case it sparks ideas for you.
Cumbersome Prerequisite Setups: Note that prerequisite MSI files are not so bad for corporate deployment since deployment systems will allow one to define relationships between MSI files and to set up deployment chains. For home users you can easily wrap everything in a large setup.exe.
Nonsense Options: Options that don't make sense would be to roll the new file into both setup versions. No gain, lots of overhead. Some people like to copy new files locally to the main installation folder. Does not work since the files it is linked to are likely elsewhere (runtime location). Static linking wouldn't be relevant in this case I think. Only as a last resort to solve a live problem I guess. Setting the SharedDllRefCounter flag will not affect MSI reference counting, it is for legacy reference counting (non-MSI setups), though tweaking this manually is an emergency "solution". The last resort people end up with is typically to abandon the runtime installation and install everything to the same installation folder. Then you have to always recompile everything for every release - which is what you want to avoid?
Some Links:
WiX (Windows Installer Xml), Create universal variables
Pre-Processor constructs, features, Burn Bundles and beyond

Specific advantages of MSI based installation over MSI wrapped script based installation?

Disclaimer: I've still never gotten beyond the most basic WiX tutorial, because every time I try to understand the concepts, my head starts spinning.
I've been reading Is it feasible/sensible to wrap an InnoSetup installer inside an MSI for easier distribution via AD? :
There is a tool (look for exemsi MSI wrapper) today that can wrap a script/exe based installer, like InnoSetup, and provide install, upgrade and uninstall.
From my experience, that's what users expect: Can install product, newer setups can upgrade it, uninstalling will remove product.
Yet quite a few answers on that question state that only a "true" MSI can reliably provide "all"(?) required(?) features.
So, given that what I always thought an installer was supposed to do is:
Install product with as little hassle as possible
Allow repairing a product (possibly by simply running the setup again)
Allow upgrading of product via a newer setup
eventually uninstall the product, leaving as little trace as possible.
The question is, given that it is proven that, given the right tool, the points above are possible by simply wrapping an exe in an MSI, what additional advantages do "real" MSI packages offer?
To be clear here: An MSI package does (seem to) offer additional benefits for enterprise / AD / GPO distribution, that you don't have if you have a bare .exe installer - I don't question that. What I'm interested in is what - actually used - features are only possible through a "real" MSI package?
MSI supports installing additional features on demand. A shortcut (.lnk) created by MSI contains special metadata recognized by Windows and can automatically repair and/or install missing features.
Another advantage is that non-administrators can install patches without UAC elevation if the package is signed.
Some disadvantages of MSI are:
Cannot create a single .msi for 32-bit and 64-bit targets.
Single user/non-elevated installers can be problematic because the support for this has changed over time and new MSI properties have been added.
Depending on your minimum supported Windows version you might have several major versions of MSI to test/deal with.
Bloats your system drive by storing the full .msi in %windir%\Installer on recent versions of Windows.
Bloats the registry by storing the path and other information about every single file it installs.
Installation or removal operations are by Feature (of a Product). This is not as relevant as it used to be because of the trend toward smaller installers with fewer questions being asked of users. For large installers, for example Visual Studio and SQL Server, questions are asked via bootstrappers--the opposite of what you are considering.
Installation, repair and removal are by Component (across all Product and Version). Reference counting is under the control of Windows Installer and is less likely to become corrupted than the pre-Windows Installer technique. Shared components are now less common because of different application technologies such as .NET and registration-free COM. Large systems might share components but again they might be divided into separate installers so that no Component is needed by more than one Product.
Whether these are advantages depends on the needs of your installation architecture.
MSI supports advertisement of the available application without installing them (more details in this MSDN post). It's handy in a corporate environment as it allows deploying only the most essential applications and 1) saves physical space on user machines; 2) reduce expenses for apps with per-user licensing (only those who really need that app will actually install it and activate the license).

WiX - VC++ Runtime - vcredist vs merge module

I am building a MSI installer using WiX. As the product that is supposed to be installed requires a VC++ runtime I found the two option of doing that which are (a) using the corresponding merge module and (b) using burn to run vcredist prior to the actual product's MSI. To differ between those two options I have some questions I didn't find the information on.
1) If using the merge module the runtime is not installed separately (no entry in add and remove programs) but as far as I understand just copies the required files to their corresponding locations.
1.1) If there already is an installation of vcredist present on the system I suppose the merge module does nothing during the product's installation?
1.2) If there was a vcredist installation present as mentioned in 1.1) what happens if the user just uninstalls that runtime via add and remove programs? I suppose the product does not work anymore (at least until a repair installation is performed which causes the merge module stuff in the MSI to re-add the necessary files?)
1.3) If the vcredist was not yet installed and the MSI installer copies the files to the system and after that another installer or the user is calling the vcredist.exe what is happening then? Does vcredist reports the runtime as already being installed?
1.4) If uninstalling the product are the files copied to the system via the merge module being removed?
1.5) If the answer to 1.4) yes (VC++ runtime files are removed): If there are two different products are installed on the system both using the same merge module internally and one of the two products is uninstalled what happens to the installed runtime files? Are they removed and the other product is not working anymore due to the missing runtime files?
Thanks in advance for your help and information.
Regards,
Gunnar
A merge module is just a consistent way to install (usually shared) files properly by including them in a build. As an analogy, the C++ compilers build .obj files that are combined into an exe, but you can no longer talk about an obj having a separate existence after the exe is built and running. It's the same with merge modules. Once they are in the MSI they are just files to install, and they follow the standard rules. If a file is already installed (in the shared location) it will be overwritten if the incoming version is higher than the already installed version. Its containing component will be ref counted up by one, and uninstalling other products (including the VC redist) using the component will ref count down so that any products using the file don't break - there is still a version for them to use.This is just the standard sharing method for files shared amongst products, and it makes no difference that one product is a VC redist and the other is your MSI. It could just as easily be several of your products that each install the files using merge modules and each can be uninstalled without breaking the others because of the ref counting and that fact that the shared location and common component ID makes the sharing work as intended. So forget that one product is the VC redist and the other is yours (or another that uses the same files) - it's all just the Windows Installer's shared file/ref counting mechanism.
This is for the recent merge modules that install the files to the system folder. There have been other schemes using WinSxS and policy redirects that don't seem to be used now (VS 2015).

What to put into a Windows Installer MSI directly vs. a wrapper/boostrapper?

Background
I'm currently triaging migrating an existing non-MSI setup to a Windows Installer based solution. The current solution is written in InnoSetup and I very much like it, however, customer IT departments start to require MSI, and where they do so, it is often the case, that many/some of the prerequisites and scripts we include in our setup.exe are not needed for their automated tasks (but, then, some are).
Therefore it seems a pure MSI wrapper doesn't make too much sense here, so I'm looking at (multiple?) MSI files plus a boostrapper.
Prior knowledge
I'm good an InnoSetup, but I'm just starting to read into the Windows Installer technology.
Question
As far as I can tell, for any multistep / "complicated" setup requirements including prerequisites and stuff, using just a bare MSI file is a no-go. (As evidenced by the existence of all the different boostrappers, including the one bundled with WiX, Burn)
Therefore, I would need to split our existing monolithic setup into several steps, some of which (mostly those that install our files) bundled into MSI databases and some of the steps just "scripted" in the bootstrapper.
And here is where I really could use some prior experience regarding setup packages: What parts of a (chained) setup go into the MSI package(s) and what part goes into the bootstrapper?
Should all the (normally visible) UI reside in the bootstrapper or do you put some of it into the MSI files?
How "dumb" should each MSI file ultimately be? That is, if using a bootstrapper and multiple MSI files anyway, should any individual MSI file contain any optional parts, or should all the options be factored out into separate MSI files (that just check for the existence of their respective prerequisites, but contain no logic to install them)?
Basically, the application (suite) needs to support a click-through average user scenario where the setup handles everything and for corporate clients needs to be able to be split up into MSI files that only contain our stuff minus dependencies like the .NET runtime, SQL Server, ... that'll be handled by the client's corporate IT and our software MSIs will be deployed by the client IT automagically.
So, should all the glue and dependency scripting go into the bootstrapper and only use very simple MSI files? Or should some "logic" go into (some) MSI files?
Short-ish answer:
When there are multiple MSI files it is normal for the UI to be handled by the Burn bootstrapper because you do want to see combined progress, not all the separate MSI UIs. You also should set up appropriate rollbacks of more than one MSI in the event of a failure of one if you are really packaging several MSIs as a product, so if one fails they all need backing out.
The bootstrapper contains detection logic that determines what needs installing, and can install prerequisites like SQL, NET etc, but must not otherwise change the system.
The MSI files contain all the files, service installation, COM registration and so on that is appropriate for the files being installed. Any custom action code you use that alters the system must be in the execute sequence, deferred, and have a corresponding rollback CA to undo whatever it does. The MSI should be capable of being run independently to install its content - I've found that to be a useful guideline. The MSI files will be installed without their UI, so ensure that they can be installed silently with parameters passed as property values on the command line, including install location.
Hard to answer this in brief. Do use Burn or a similar bootstrapper, and leave runtimes with their own deployment solution as a separate file to run - and run in silent mode by default.
For home users you should install everything without too many questions to avoid confusion.
For corporate deployment you should deploy only what is needed and make it clear what each included deployment file is for:
Write a one page PDF with deployment instructions describing what every file does and what runtime it relates to. Call it "DEPLOYMENT README.TXT" or similar. This is the best way to get your application approved for corporate deployment. It can be tiresome to analyze this.
Application packagers in the corporate environment will analyze the prerequisites and determine if your application will work well with their standard framework packages. These standard packages will be set as a prerequisite in the distribution system.
Document in particular what .NET framework version is needed and other runtime requirements in detail.
Don't install windows hotfixes, msiexec engine updates or .NET framework runtimes automatically. Document them as prerequisites in your text file. These runtimes are tightly controlled in corporate settings and they are deployed by customized corporate packages.
You can include merge modules of simple runtimes in your MSI, they can be easily removed by the application packaging team in the corporate setting.
This answer didn't get terribly good, but I am out of time. Perhaps check this answer as well:
MSI Reference Counting: Two products install the same MSIs

Build one MSI from separate components

We have a product that has three parts:
Application files (exe and dll files)
Help files
SSRS reports
All three things get installed together with the same installer built using WIX. In our company, each component is developed by separate teams and with different deadlines. We would like to break our MSI into three parts so that when one part becomes stable its installer part is also stable and is not rebuilt from scratch when the other parts are updated.
I've looked at merge modules and CAB files but I think that's the wrong direction. Is there anything in the WIX toolset that can help me achieve my aims?
(I have read the question Building MSI Installer and Separaete Installation Files but believe this question is a bit different.)
Thanks for your help.
WiX library (*.wixlib) seems to be the best approach to distribute the components in your case.
I would organize this process like this:
each team has a separate WiX installation project (Setup Library Project), which compiles into *.wixlib file instead of the MSI (or MSM) package
each project is evolved as the component is developed, and the output is shared to other teams
an integration build gathers all wixlib libraries and links (light.exe) them all together into a single MSI package
Hence, you'll always have a final installation package with the latest builds of components, which is what continuous integration is all about.
As far as I understand, you won't distribute the components separately, and for the end user it is still a solid installation package. Hence, merge modules could be an overhead. I suspect (but not sure) that light.exe performs some extra validation when linking the libraries, comparing to merging tool.
Well, merge modules are a solution. You could have two merge modules containing the help files ans SSRS reports, and add them in the main package that will contain only the application files. This can increase build time if nothing is changing in the two merge modules but you will still have a long build time for the main package changes.
Another option is to create separate packages for each of the components and bundle them into a single one using Burn. I would recommend using the merge modules, its more cleaner and easy to manage.