Aaron Stebner's WebLog

Thoughts about setup and deployment issues, WiX, XNA, the .NET Framework and Visual Studio

Installing an assembly to the GAC and the local file system

Installing an assembly to the GAC and the local file system

  • Comments 23

Some products require that assemblies be installed to both the global assembly cache (GAC) and to the local file system.  Windows Installer has native functionality that allows a setup author to do both.  You can author an assembly as a global assembly (which will cause Windows Installer to install the file to the GAC) by adding it to the MsiAssembly and the MsiAssemblyName tables of the MSI and setting the File_Application column of the MsiAssembly table to Null.  You can author an assembly as a private assembly (which will cause Windows Installer to install the file to the local file system) by adding it to the MsiAssembly table and setting the File_Application column to a file entry from the File table of the MSI.  Windows Installer will take the file entry, look up the component that owns it and then use the directory entry associated with that component to install the private assembly to that same directory.

One of the first questions that comes up when a setup developer is trying to install an assembly to multiple locations is how to author the data in the MSI to install the same assembly component to both the GAC and the local file system.  In most cases where a setup needs to install the same file to multiple locations, you can use the DuplicateFile table.  Unfortunately, the DuplicateFile table does not support installing an assembly as both a global and a private assembly.  In other words, you have the option to indicate that an assembly is a private assembly or a global assembly, but not both.  In order to install the assembly to both the GAC and the local file system, you will have to create a second component and author one component as a global assembly and the other component as a private assembly.

We have to install assemblies to both locations as part of the .NET Framework and Visual Studio setups.  In the case of the .NET Framework, the underlying architecture requires that the assemblies that are part it be installed to the GAC (for 3rd party applications) and to the local file system (for design-time scenarios in Visual Studio).  However, we had to carry 2 copies of each assembly in the setup package in order to install to both places because Windows Installer doesn't support using the DuplicateFile table to do this.  Carrying 2 copies of each assembly caused the overall size of the .NET Framework 1.0 and 1.1 redistributable setup package to grow even larger than it already was.  After looking at a lot of different options, we decided to implement a custom action solution in .NET Framework 2.0 that would manage the installation of assemblies to both the GAC and the local file system.  This allowed us to only carry a single copy of each file in the setup package and reduce the overall size of the .NET Framework setup by about 5 megabytes.  Of course, if you compare the size of dotnetfx.exe between versions 1.1 and 2.0 you won't see much of a difference.  What ended up happening was that the size of the features added in .NET 2.0 roughly cancelled out the size of the assemblies that we were carrying duplicate copies of in .NET 1.1.

 

  • Interesting post, but could you elaborate on what the custom action is doing? For example, is the MSI installing the private assembly and then the CA taking the file that was installed and installing a copy to the GAC? Thanks!
  • Hi John - thank you for the feedback. Essentially what the custom action is doing is calling the same Fusion APIs that gacutil.exe does to install a copy of the assembly to the GAC. I will have to look at the source code because I don't remember for sure if the custom action uses the private assembly (the copy already installed to the local file system) or if it uses the file carried with the setup package and installs from the source location. I believe it uses the source files because otherwise the custom action would require that 2 copies be installed. I'll confirm that this weekend and post an update here when I find out.

    Also, for reference, here is a good overview of some of the Fusion GAC APIs from a member of the Fusion development team - http://blogs.msdn.com/junfeng/articles/229648.aspx
  • Hi again John - I confirmed by looking at the custom action source code that it is using standard MSI API calls to query the contents of the Assembly and AssemblyName tables and then using the source files carried with the setup package to install to the GAC. Note that this custom action does NOT use the standard MSI tables (which are named MsiAssembly and MsiAssemblyName).
  • First off, thanks for posting this. I tried using Windows Installer (via InstallShield 10.5) to create a global assembly and use the DuplicateFile table to create local copy of the assembly. The error I am getting is "1308 Source file not found". For some reason it is trying to copy from C:\ instead of the source directory or the GAC. It this the error your would expect?
    Thanks again,
    Paul
  • Hi Paul - I am not positive what error to expect if you try to use the DuplicateFile table to install an assembly to the GAC and the local file system. When we originally designed this architecture for the .NET Framework, Windows Installer didn't even support installing assemblies to the GAC at all, so we worked with them to develop that feature and ended up authoring our MSIs with duplicated components from the beginning. I believe that since Windows Installer uses fusion APIs to install assemblies to the GAC rather than handling installation directly, that this would explain why you see a 1308 error. Since it uses fusion, Windows Installer does not have any knowledge of the exact physical location on disk for assemblies that are installed into the GAC.

  • I have used the Windows Installer that comes with Visual Studio 2003 to install a file both on the local file system and in the GAC. Steps to follow:
    1) Create a Setup project (under Setup and Deployment Projects templates).
    2) Open the File System Editor (if it is not already open) by selecting the "View -> Editor -> File System" menu item.
    3) For local file system files:
    a) Select a desired folder in which to install the files (such as Application Folder) and add one or more files to the folder (right-click on folder and select "Add -> File...", and then select file).
    b) Configure the properties for the folder to point to the desired destination folder on the target machine.
    4) For installing into the GAC:
    a) Right-click in File System Editor window and select "Add Special Folder -> Global Assembly Cache Folder" menu item to add the GAC folder to the list.
    b) Add one or more assemblies to the GAC folder (right-click on folder and select "Add -> File...", and then select file).

    5) Build your Setup project and then run the resulting Setup.exe (or execute the resulting .msi). During installation, Installer will copy the designated files to the destination on the target machine and install designated assemblies to the GAC. During removal, the Installer will reverse the installation process.
  • Hi TKent - thank you for the detailed instructions. These steps will end up creating an MSI that contains 2 components for each assembly - one to install the assembly to the local file system and another to install the assembly to the GAC.

  • I wrote this post a couple of months ago describing how to install an assembly to both the GAC and the...
  • I want a basic help in creating a web set up project which will install my assembly to the GAC and also register it using regasm to be accessed from asp web pages. All should be done when I run the MSI to install the MSI on a machine.

    Thanks and regards
    Shyamal Bhowmik
  • Hi Shyamal - There are a lot of resources available on the web for building MSI-based setups.  You can look at the Windows Installer site on MSDN at http://msdn.microsoft.com/library/default.asp?url=/library/en-us/msi/setup/windows_installer_start_page.asp.  I would also suggest trying to use WiX to build your MSI.  You can download the WiX toolset at http://wix.sourceforge.net and there is an excellent tutorial for WiX at http://wix.sourceforge.net/tutorial.

    One thing I would recommend is to not use regasm.exe as a custom action during your setup.  Instead, you should extract the registry information and install those keys/values using the Registry table of your MSI.  That will provide a more robust setup experience for your users.
  • Rob Mensching posted an item on his blog last night that I wanted to bring to your attention. Recently,

  • PingBack from http://msdnrss.thecoderblogs.com/2007/06/01/link-to-information-about-smart-cabbing-feature-in-wix-v30/

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

  • PingBack from http://www.olegsych.com/2009/03/t4toolbox-build-93211-problem/

  • I have to get the details from the manifest file of the assembly . but i don't have the source. basically i need to put the details in the MSIAssemblyName table for that assembly.How to do it?

Page 1 of 2 (23 items) 12
Leave a Comment
  • Please add 8 and 3 and type the answer here:
  • Post