DuplicateFile table with GAC - gac

My installer has grown very large b/c of file duplication. Some of our DLL's are in two places (local and GAC or local and system32 folders). How can I use the DuplicateFile table or other Installshield mechanism (installscript?) to duplicate the file in the GAC? It's the same file that needs to be copied to two locations but I only want it in the installer once because of its size.
My project type is actually Installscript MSI.
Hopefully my request is clear. Thanks!

The DuplicateFile table doesn't support deploying to the GAC because MSI doesn't uses a different pattern to deploy to the GAC then most folders. It uses MsiPlublishAssemblies which interacts with Fusion.
You have to declare 2 components ( 1 for normal and 1 for the GAC ). If size is a concern for you, WiX has a feature called smart cabbing which can create your cab and stream it into media with multiple file rows sharing the same storage.

Related

How can I avoid LGHT0306 when adding a very large file to a WiX Burn bootstrapper?

I am using WiX Burn 3.9 to create a bootstrapper (with a custom managed bootstrapper application for the UI). I'm building a tiny version of the bootstrapper (a couple of megabytes) that downloads dependencies as needed. I'm also building a version with all dependencies embedded, to support easy installation on secure networks. The /layout command line option would work for pulling down the dependencies, but my organization prefers a single, monolithic executable to keep things simple for the users.
Everything was going along pretty well until I was asked to add a 1GB virtual appliance file and associated installation readme. All the bootstrapper has to do is place them in a folder that the user specifies in the bootstrapper UI. I put the *.ova and *.htm file into a self-extracting zip executable and passed the destination folder to it on the command line. The web installer version works just fine, but then I tried to build the offline installer, with everything embedded. I started getting an error from light:
light.exe(0,0): error LGHT0306: An error (E_FAIL) was returned while finalizing a CAB file. This most commonly happens when creating a CAB file with more than 65535 files in it. Either reduce the number of files in your installation package or split your installation package's files into more than one CAB file using the Media element.
The only relevant-looking conversation about this error that I have found is here. This seems to be related to file size, not file count. I'm wondering if the problem is related to the overall size of the bootstrapper executable (which would be about 2 GB) or the size of the very large self-extracting zip executable (about 1 GB). When I'm building an MSI with WiX, the syntax for breaking things up into separate cab files is pretty clear, but I'm not sure whether the same concepts are exposed for a Burn-based boostrapper, or if it's possible to do much to embed a file of that size.
With embedded payloads, Burn uses a .cab file that it attaches to the .exe during the build process. That means there's a 2GB limit on the size of embedded payloads. There might also be a limit on how much you could attach to an .exe.
I haven't tried it but it looks like you can try attaching multiple containers by using explicit Container elements.
Unless you absolutely need a single .exe, you can also just create an uncompressed bundle. The .msi, .cab, and .exe files would be external but it works if you're creating .iso images for download (for example).

MSI Reference Counting: Two products install the same MSIs

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

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.

Forcing project to load DLL's from the current directory

I am trying to make a program that works on every operating system by forcing it to load and use the DLL's in the current directory, not the windows directory, but it don't works. I tried to enable "copy local" and change the refference path, but without any success, the program tries to load the DLL's from the windows directory.
My question is: how can I fix this?
The Search Order for DLL's is documented here on MSDN. It also includes instructions on how you can modify the search order so that the local bin directory is searched first, instead of the GAC.
The directory %windir%\assembly is called the GAC. Assemblies are not copied there, but installed typically using gacutil /i or by installation packages.
GAC is a suitable folder for libraries referenced by lots of other libraries and applications in build versions that are not centrally coordinated. Using GAC allows you to have multiple versions of the same library, all of which might be indirectly required even by a single application, installed side by side on the system. Case in point is the .NET framework itself.
The assemblies that you build are probably not that kind. Application assemblies and libraries that are basically part of a single application should never make it to the GAC or you can get into trouble. There is a variety of possible trouble:
one accidentally or intentionally creates different (incompatible) builds of the same library with the same version number.
assembly in GAC references an assembly not in GAC
one app installs the same assembly into GAC, but another app wants to load it from its local folder (where application binaries reside).
Code in the GAC gets a preference when assemblies are loaded. To remove an assembly from the GAC, use gacutil /u.

Switching from WiX 3.0 to 3.5 decreased msi size from 100Mb to 4Mb?

After upgrading my installer build to WiX 3.5 the msi size fell from 100Mb down to only 4Mb! At first I thought some files were excluded from MSI, so I ran light.exe 3.0 and 3.5 with -v (verbose) and -notidy (to keep the temp files) options, checked the cab files, and indeed in case of 3.5 the cab file was 3.8Mb while the 3.0 produced 98Mb. Looking inside the cab, all the files seem to be present. Tried extracting both cabs -- the output looks identical. Finally, still not believing my eyes I installed the 4Mb MSI and it worked! What can explain such a drastic difference? My current theory -- perhaps the new WiX uses new CAB compressin logic which detects duplicate files and creates references instead of adding the file multiple times? The MSI linking time dropped significantly as well... My program consists of 20+ folders with pretty much same DLLs duplicated in all of them...
Wix 3.5.0619.0 included the following change (from http://wix.sourceforge.net/releases/3.5.2519.0/history.txt):
Smart cabbing now catches ALL
duplicate files, not just ones from
the same source path (based on file
hashes).
I have also observed a similar reduction in installer size after an upgrade from Wix 3.0 to 3.5. The above change would account for this, as there is some duplication in the files our installer is delivering, and these would only be picked up by file hashes not source paths.
Did you have different source paths in your 3.0 and the same source path in your 3.5?
WiX Smart Cabbing
Can you share the MSIs somewhere (feel free to contact me offline if you prefer, see http://robmensching.com)? There are no changes that I know of in WiX v3.5 that could cause that sort of drastic change... unless your .wxs files changed... or there is a bug. ;)