Mailbag: How can I install a file to the GAC and the local file system using WiX syntax?

Question:

I am creating an MSI-based setup using WiX.  One of the files that I am installing is authored like this:

<DirectoryRef Id="MyDirectory">
    <Component Id="MyComponent" Guid="PUT-GUID-HERE" DiskId="1">
        <File Id="MyAssembly" Name="MyAssembly.dll" Assembly=".net" KeyPath="yes" Source="MyAssembly.dll" />
    </Component>
</DirectoryRef>

When I create an MSI and install it, I see MyAssembly.dll gets installed to the global assembly cache (GAC), but it does not get installed to MyDirectory.

How can I author my MSI using WiX so that it will install to both the GAC and a local directory?

Answer:

When you use the attribute Assembly=".net" for a file in WiX, it will create entries in the MsiAssembly and MsiAssemblyName table for this component and mark it as a GAC component.  That means that the file will only be installed to the GAC by this component, and it will not install to the directory that the component is a child of.  That directory will only be used by Windows Installer to stage a copy of that file when creating and administrative install point.

If you need to install the file to both the GAC and the local file system, you will need to author a second component that contains another copy of this file and make sure to not include Assembly=".net" in that second component.

Heath Stewart has posted some sample WiX syntax in this blog post that can be used as a guide for authoring components to install a file to both the GAC and the local file system.  I want to call out a couple of key points about this scenario:

  • Normally, if you need to install the same files to multiple locations, you could use the DuplicateFile table.  However, as I briefly described in this blog post, Windows Installer does not support using the DuplicateFile table to install a file to both the GAC and the local file system, so that necessitates creating a 2nd component in this scenario.
  • In order to avoid ICE30 errors in your MSI, you need to make sure that the component that installs the file to the GAC is a child of a different directory than the component that installs the file to the local file system.  The directory for the GAC component will only be used by Windows Installer to stage a copy of that file when creating and administrative install point, so it does not really matter what it is named as long as it is different than the directory that the other copy of this file is installed to.
  • Ordinarily, having two components that install the same file would result in your package containing two copies of this file (which therefore increases your installer's size).  However, in recent builds of WiX 3.0, the new "smart cabbing" feature (described in this post on Rob Mensching's blog) will automatically fix up the cab file to only contain one physical copy of the file to eliminate this size issue.