Global Assembly Cache (GAC) and .NET Framework Insights
In this post I want to collect from several sources about what exactly is the GAC and how to manage it. Further we will focussing on the .NET Framework and its components, where the GAC is only one of them.
Global Assembly Cache (GAC)
Each computer where the Common Language Runtime (CLR) is installed has a machine-wide code cache called the Global Assembly Cache. The Global Assembly Cache stores assemblies specifically designated to be shared by several applications on the computer.
The CLR and GAC will be installed alongside the .NET Framework. With .NET Core you can install the CLR separately.
You should share assemblies by installing them into the Global Assembly Cache only when you need to. As a general guideline, keep assembly dependencies private, and locate assemblies in the application directory unless sharing an assembly is explicitly required. In addition, it is not necessary to install assemblies into the Global Assembly Cache to make them accessible to COM interop or unmanaged code.
Global Assembly Cache
There are two ways to deploy an assembly into the Global Assembly Cache:
- Use an installer designed to work with the Global Assembly Cache. This is the preferred option for installing assemblies into the Global Assembly Cache.
Windows Installer, the Windows installation engine, is the recommended way to add assemblies to the global assembly cache. Windows Installer provides reference counting of assemblies in the global assembly cache and other benefits. To create an installer package for Windows Installer, use the WiX toolset extension for Visual Studio 2017.
- Use a developer tool called the Global Assembly Cache tool (Gacutil.exe), provided by the Windows SDK.
Working with Assemblies and the Global Assembly Cache
Where is the GAC located?
Starting with the .NET Framework 4, the default location for the Global Assembly Cache is %windir%\Microsoft.NET\assembly. In earlier versions of the .NET Framework, the default location is %windir%\assembly.
GAC_32 vs GAC_64 vs GAC_MSIL folders
%windir%\Microsoft.NET\assembly\GAC_32 for assemblies targeting 32-bit.
%windir%\Microsoft.NET\assembly\GAC_64 for assemblies targeting 64-bit.
%windir%\Microsoft.NET\assembly\GAC_MSIL for assemblies targeting Any platform.
CorFlags.exe (CorFlags Conversion Tool)
There is a flag in the assembly’s header which determines the version . You can see and set this flag using corflags.exe, part of the .NET SDK.
Determine Assembly version 32 bit or 64 bit or any with corflags.exe
For this example I will check the Azure.Storage.Files.Shares.dll client library for .Net to work with the Microsoft Azure Storage File Shares.
Regarding the flags parameter shown in the screenshot, this dll supports both platforms, 32-bit and 64-bit (Any).
Any CPU: PE = PE32 and 32BIT = 0
x86 bit: PE = PE32 and 32BIT = 1
64-bit: PE = PE32+ and 32BIT = 0
Assemblies deployed in the Global Assembly Cache must have a strong name. When an assembly is added to the Global Assembly Cache, integrity checks are performed on all files that make up the assembly. The cache performs these integrity checks to ensure that an assembly has not been tampered with, for example, when a file has changed but the manifest does not reflect the change.
Strong-naming an assembly creates a unique identity for the assembly, and can prevent assembly conflicts.
What makes a strong-named assembly?
A strong named assembly is generated by using the private key that corresponds to the public key distributed with the assembly, and the assembly itself. The assembly includes the assembly manifest, which contains the names and hashes of all the files that make up the assembly. Assemblies that have the same strong name should be identical.
When a strong-named assembly is created, it contains the simple text name of the assembly, the version number, optional culture information, a digital signature, and the public key that corresponds to the private key used for signing.
Do not rely on strong names for security. They provide a unique identity only.
You can also place multiple assemblies with the same name and same version into the GAC as long as they have different strong names.
Why strong-name your assemblies?
For .NET Framework, strong-named assemblies are useful in the following scenarios:
- You want to enable your assemblies to be referenced by strong-named assemblies, or you want to give
friendaccess to your assemblies from other strong-named assemblies.
- An app needs access to different versions of the same assembly. This means you need different versions of an assembly to load side by side in the same app domain without conflict. For example, if different extensions of an API exist in assemblies that have the same simple name, strong-naming provides a unique identity for each version of the assembly.
- You do not want to negatively affect performance of apps using your assembly, so you want the assembly to be domain neutral. This requires strong-naming because a domain-neutral assembly must be installed in the global assembly cache.
- You want to centralize servicing for your app by applying publisher policy, which means the assembly must be installed in the global assembly cache.
For .NET Core, strong-named assemblies do not provide material benefits.
If you are an open-source developer and you want the identity benefits of a strong-named assembly for better compatibility with .NET Framework, consider checking in the private key associated with an assembly to your source control system.
NuGet Package Manager
NuGet is a package manager for developers. It enables developer to share and consume useful code. A NuGet package is a single ZIP file that bears a .nupack filename extension and contains .NET assemblies and their needed files.
NuGet was initially distributed as a Visual Studio extension. Starting with Visual Studio 2012, both Visual Studio and Visual Studio for Mac can natively consume NuGet packages. NuGet’s client, nuget.exe is a free and open-source, command-line app that can both create and consume packages. MSBuild and .NET Core SDK (dotnet.exe) can use it when it is present. NuGet is also integrated with SharpDevelop.
An introduction to NuGet
For .NET (including .NET Core), the Microsoft-supported mechanism for sharing code is NuGet, which defines how packages for .NET are created, hosted, and consumed, and provides the tools for each of those roles.
Fuslogvw.exe (Assembly Binding Log Viewer)
The Assembly Binding Log Viewer displays details for assembly binds. This information helps you diagnose why the .NET Framework cannot locate an assembly at run time. These failures are usually the result of an assembly deployed to the wrong location, a native image that is no longer valid, or a mismatch in version numbers or cultures. The common language runtime’s failure to locate an assembly typically shows up as a TypeLoadException in your application.
.NET Framework is a technology that supports building and running Windows apps and web services.
.NET Framework documentation
.NET Framework 4.8 is the last version of .NET Framework, and no further versions will be released. However, .NET Framework will continue to be serviced with monthly security and reliability bug fixes. Additionally, it will continue to be included with Windows, with no plans to remove it. You don’t need to migrate your .NET Framework apps, but for new development, use .NET 5.0 or later.
.NET Framework consists of the common language runtime (CLR) and the .NET Framework class library.
The common language runtime is the foundation of .NET Framework. Think of the runtime as an agent that manages code at execution time, providing core services such as memory management, thread management, and remoting, while also enforcing strict type safety and other forms of code accuracy that promote security and robustness. In fact, the concept of code management is a fundamental principle of the runtime. Code that targets the runtime is known as managed code, while code that doesn’t target the runtime is known as unmanaged code. The class library is a comprehensive, object-oriented collection of reusable types that you use to develop apps ranging from traditional command-line or graphical user interface (GUI) apps to apps based on the latest innovations provided by ASP.NET, such as Web Forms and XML web services.
Download .NET Framework
What is GAC?
Gacutil.exe (Global Assembly Cache Tool)
.NET Framework Tools
Microsoft .NET: Implement a Custom Common Language Runtime Host for Your Managed App
How to: Determine which .NET Framework versions are installed
Find CLR versions
The Clrver.exe tool
Use the CLR Version tool (Clrver.exe) to determine which versions of the CLR are installed on a computer. Open the Developer Command Prompt for Visual Studio and enter
Microsoft .NET: Implement a Custom Common Language Runtime Host for Your Managed App