Installing an assembly to the GAC and the local file system
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.
Comments
Anonymous
July 26, 2005
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!Anonymous
July 30, 2005
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.aspxAnonymous
August 01, 2005
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).Anonymous
August 10, 2005
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,
PaulAnonymous
August 13, 2005
The comment has been removedAnonymous
August 22, 2005
The comment has been removedAnonymous
August 22, 2005
The comment has been removedAnonymous
September 02, 2005
I wrote this post a couple of months ago describing how to install an assembly to both the GAC and the...Anonymous
April 27, 2006
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 BhowmikAnonymous
April 27, 2006
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.Anonymous
June 01, 2007
Rob Mensching posted an item on his blog last night that I wanted to bring to your attention. Recently,Anonymous
June 01, 2007
PingBack from http://msdnrss.thecoderblogs.com/2007/06/01/link-to-information-about-smart-cabbing-feature-in-wix-v30/Anonymous
June 21, 2007
Question: I am creating an MSI-based setup using WiX . One of the files that I am installing is authoredAnonymous
March 26, 2009
PingBack from http://www.olegsych.com/2009/03/t4toolbox-build-93211-problem/Anonymous
April 22, 2012
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?Anonymous
April 23, 2012
Hi Dev - If you are using WiX to build your MSI, it will automatically scan the assembly and populate the values in the MsiAssemblyName table for you. If you're not using WiX, you can use a tool like Reflector to look at the assembly and figure out the assembly identity, and then populate the appropriate values into the MsiAssemblyName table of your MSI.Anonymous
April 25, 2012
The comment has been removedAnonymous
April 26, 2012
The comment has been removedAnonymous
May 03, 2012
thanks Aaron - I am facing one more problem: while adding entries to MsiAssembly and MsiAssemblyName Table of msi database using MsiOpenDatabaseView() method it is justing failing with the error code - 1615. This is the case with only these two tables. At First I thought It would be due to the reason that I dint change the Application Type to .NET. but after changing that also it is not working. Then I tried updating _Validation table for the entries of MsiAssembly and MsiAssemblyName tables. It too dint work out. Probably I am missing some dependency which is hindering the records to be entered in MsiAssembly and MsiAssembly Tables. can u give me some clue or hint about this problem?????? thanks.Anonymous
May 03, 2012
The comment has been removedAnonymous
May 03, 2012
The comment has been removedAnonymous
May 03, 2012
Hi Dev - It sounds like the MsiAssembly table isn't a part of the database schema that your MSI is using or something like that. I'm not sure about how to fix that type of error though, so I think you may need to post a question on one of the Windows Installer forums and see if someone there can help suggest ideas for how to fix this type of error. I'm sorry that I'm not able to be more helpful in this scenario.Anonymous
May 06, 2012
Thanks Aaron - I have somewhat resolved the issue . basically some of the msi database tables are reported to be unknown when they are empty. If they contain atleast one record then everything works fine while inserting records. so I edited the generic msi file we use for packaging by inserting a dummy file entry. but I think it is not an intelligent fix.......nyways I will try for some other better fix. thanks for guiding.