Installing Assemblies for Runtime and Design-time Use

The Microsoft .NET Framework installs assemblies into two different locations, and this practice is recommended to developers wishing to deploy assemblies both for runtime and design-time use.

Runtime assemblies are those assemblies needed for an application to execute. It is recommended that you add runtime assemblies to the Global Assembly Cache (GAC). If you’re deploying your assemblies in a Windows Installer package, you would add the file normally but then add records into the MsiAssembly and MsiAsemblyName tables. If you plan on doing in-place updates – though assembly versioning is recommended – be sure to add the FileVersion attribute to the MsiAssemblyName table.

Design-time assemblies are those assemblies you would compile and link against when building your own managed assemblies. In Visual Studio, these are assemblies you would see when you right-click on a project, for example, and click “Add References…”. These assemblies are installed as any other normal files would be installed using Windows Installer, with the addition of a registry key under SOFTWAREMicrosoft.NETFrameworkAssemblyFolders – either under HKEY_LOCAL_MACHINE for all users, or HKEY_CURRENT_USER for the current user.

Since the .NET Framework provides the base class library, all the assemblies are co-installed into both locations. Components from other vendors may also do the same, while end user applications may install only into the GAC. Developers really should only install design-time assemblies they want users to reference in their own projects. These assemblies will certainly work with dependent assemblies installed only into the GAC.

An example WIX fragment follows. This was updated from the previous snippet to pass ICE30 validation and add the Assembly attribute that was mistakenly left out originally. Thanks to Aaron Stebner for pointing this out.

<Directory Id=ProgramFilesFolder>

    <Directory Id=ProductDirectory Name=$(var.ProductName)>

        <Directory Id=GAC Name=GAC>

            <Component Id=RT_MyControl Guid=22887611-B13E-41EE-897C-D78830E68AEB DiskId=1>

                <!– Runtime, assembly in GAC –>

                <File Id=F_RT_MyControl Name=MyCtrl.dll LongName=MyControl.dll Source=$(var.SrcPath)MyControl.dll KeyPath=yes Assembly=.net/>

            </Component>

        </Directory>

        <Component Id=DT_MyControl Guid=FB935B7D-D2BD-4B83-A26C-A9376EBA0915 DiskId=1>

            <!– Design-time, private assembly –>

            <File Id=F_DT_MyControl Name=MyCtrl.dll LongName=MyControl.dll Source=$(var.SrcPath)MyControl.dll KeyPath=yes/>

            <Registry Id=R_DT_MyControl_AssemblyFolders Root=HKLM Key=SOFTWAREMicrosoft.NETFrameworkAssemblyFolders[ProductName] Value=[$DT_MyControl] Type=string/>

        </Component>

    </Directory>

</Directory>