Click here to Skip to main content
15,879,490 members
Articles / Programming Languages / C#
Article

GAC API Interface

Rate me:
Please Sign up or sign in to vote.
4.57/5 (15 votes)
14 Sep 20044 min read 124.1K   2K   41   18
An implementation of the undocumented GAC API in C#

Introduction

The GAC (aka Global Assembly Cache) is the central repository for assemblies installed on a Windows machine. It provides a uniform, versioned and safe access of assemblies by their strong assembly name. This article shows the official way how to use this GAC from your application.

A few readers might have wondered, how do I access the GAC? The internal structure of the GAC is not documented in the MSDN library but the filesystem structure (e.g. C:\WINDOWS\assembly) seems simple enough to scan it. There is however an undocumented COM API to access the GAC the (sort of) official way. This is called the Fusion API because it is implemented by fusion.dll.

Background

The basis of this work is the unofficial documentation of the GAC API in the Microsoft KB article #317540 DOC: Global Assembly Cache (GAC) APIs Are Not Documented in the .NET Framework Software Development Kit (SDK) Documentation. This article explains in detail the use of the GAC API as implemented in fusion.dll. This DLL contains a few API calls to create COM interfaces to various GAC related functionality like adding or removing assemblies, enumerating installed assemblies and the like. What we did here is to simply implement this API including the COM interfaces in C# and adorn the code with the documentation snippets from the mentioned KB article.

There is another way to use this API and this way depends on the implementation of the GAC API inside the .NET framework. Obviously the .NET framework has full access to the GAC for various reasons, even though this access is not documented and flagged internal. The CodeProject article Article "Undocumented Fusion" by John Renaud describes nicely how to use this internal implementation through reflection. This article is also insightful and describes some aspects of the API (like the history for instance) that is left undocumented in the KB article. We only give the naked implementation of the fusion.dll API and we recommend Johns article as extra background reading and for examples.

Using the code

The first step should be to read the Microsoft KB article linked above. We added almost all of this documentation as comments in our source for reference. This should give you an idea what part of the API you actually need. The examples we give here in this article all focus on the task of scanning the GAC for installed assemblies. As a side note, you should be familiar with the COM marshalling. See class System.Runtime.InteropServices.Marshal and

System.Runtime.InteropServices.IntPtr
.

The following bits of code focus on how to scan the GAC. We start by creating the enumeration interface.

C#
IAssemblyEnum ae = AssemblyCache.CreateGACEnum();

This wraps the basic call to CreateAssemblyEnum. On this interface we can now enumerate GetNextAssembly until the call return a COM error.

C#
IAssemblyName an; 
AssemblyName name; 
while (AssemblyCache.GetNextAssembly(ae, out an) == 0) 
{ 
    name = GetAssemblyName(an); 
    .... 
} 

The method GetAssemblyName (not part of the downloadable sources) uses several IAssemblyName methods to retrieve all necessary values to build a .NET-AssemblyName instance. We will show them in turn.

C#
private AssemblyName GetAssemblyName(IAssemblyName nameRef)
{
    AssemblyName name = new AssemblyName();
    name.Name = AssemblyCache.GetName(nameRef);
    name.Version = AssemblyCache.GetVersion(nameRef);
    name.CultureInfo = AssemblyCache.GetCulture(nameRef);
    name.SetPublicKeyToken(AssemblyCache.GetPublicKeyToken(nameRef));
    return name;
}

GetName is an example how to obtain strings from the COM-API. If you are not familiar with the COM marshaling of C#, you might wonder about the use of the StringBuilder. It is marshaled as a changeable char*. Using ref string instead will lead to marshaling errors since string is immutable.

C#
public static  String GetName(IAssemblyName name)
{
    uint bufferSize = 255;
    StringBuilder buffer = new StringBuilder((int) bufferSize);
    name.GetName(ref bufferSize, buffer);
    return buffer.ToString();
}

Another interesting case is the method GetPublicKeyToken. It relies on the IAssemblyName COM-function GetProperty which uses a variant type for returning values:

C#
[PreserveSig]
int GetProperty(ASM_NAME PropertyId, IntPtr pvProperty, ref uint pcbProperty);

We use a System.Runtime.InteropServices.IntPtr type to marshal this variant. The downside is that we have to extract the desired values out of this bulk of bits manually. The class System.Runtime.InteropServices.Marshal is of great service here:

C#
public static byte[] GetPublicKey(IAssemblyName name)
{
    uint bufferSize = 512;
    IntPtr buffer = Marshal.AllocHGlobal((int) bufferSize);
    name.GetProperty(ASM_NAME.ASM_NAME_PUBLIC_KEY, buffer, ref bufferSize);
    byte[] result = new byte[bufferSize];
    for (int i = 0; i < bufferSize; i++)
        result[i] = Marshal.ReadByte(buffer, i);
    Marshal.FreeHGlobal(buffer);
    return result;
}

This concludes the example. You find a few more wrapper methods in the downloadable sources but for the most part you need to write the ones you need along the lines sketched above.

Compatibility

This code is known to work with .NET 1.1 and 2.0. Please note that the DLL fusion.dll is different in 1.1 and 2.0. So if you have both frameworks installed, make sure to point the code to the right DLL. Otherwise most API-calls will fail. The default implementation uses the one found in the WINDOWS directory.

History

  • Version 1.0: submitted on 12th September 2004

Copyrights

No copyright reserved.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here



Comments and Discussions

 
GeneralMy vote of 5 Pin
David A. Gray17-Sep-12 18:56
David A. Gray17-Sep-12 18:56 
QuestionBug? Pin
Dmitri Nеstеruk9-Nov-09 10:15
Dmitri Nеstеruk9-Nov-09 10:15 
QuestionSearching for a particular assembly Pin
stickjuice3-Jul-08 5:10
stickjuice3-Jul-08 5:10 
AnswerRe: Searching for a particular assembly Pin
Bord863-Apr-12 21:49
Bord863-Apr-12 21:49 
GeneralSee &quot;Managed GAC API Wrappers&quot; for alternate solution Pin
ToolmakerSteve21-Aug-07 5:37
ToolmakerSteve21-Aug-07 5:37 
Great to see that you have written a Code Project article about accessing GAC from C#.

I recently discovered a complete C# wrapper for the Fusion API's has been written, so I mention this for other searchers:
Junfeng Zhang - Sample Managed GAC API Wrappers
http://blogs.msdn.com/junfeng/articles/229649.aspx[^]

Thanks,
ToolmakerSteve

P.S. I am using Zhang's solution since I discovered it before the one here at Code Project. I haven't yet looked at the one here, so I don't know how the two compare. I am posting simply because I like to know about alternate approaches, so I figure others will also.
GeneralGreat Code! Small Error. Pin
Gio Palacino21-Aug-06 7:23
professionalGio Palacino21-Aug-06 7:23 
QuestionHow to install new assembly Pin
Sameer Vartak21-Aug-06 6:39
Sameer Vartak21-Aug-06 6:39 
QuestionRe: How to install new assembly Pin
Harkamal Singh5-Jul-07 18:01
Harkamal Singh5-Jul-07 18:01 
QuestionHow do i get assemblies from IAssemblyEnum Pin
Vijaya Shanthi30-Jul-06 23:55
Vijaya Shanthi30-Jul-06 23:55 
General.Net 2.0 CreateStream deprecated param Pin
christopherrutter15-Feb-06 9:18
christopherrutter15-Feb-06 9:18 
GeneralFramework 2.0 Pin
Ian2328-Nov-05 1:28
Ian2328-Nov-05 1:28 
GeneralRe: Framework 2.0 Pin
christopherrutter15-Feb-06 9:39
christopherrutter15-Feb-06 9:39 
GeneralRe: Framework 2.0 Pin
JasonShort16-Mar-07 9:17
JasonShort16-Mar-07 9:17 
QuestionGetPublicKey bug? Pin
Anonymous3-Aug-05 1:11
Anonymous3-Aug-05 1:11 
QuestionCan you show how to compile this? Pin
Michael Cowan3-Mar-05 19:53
Michael Cowan3-Mar-05 19:53 
AnswerRe: Can you show how to compile this? Pin
atoenne5-Mar-05 19:03
atoenne5-Mar-05 19:03 
AnswerRe: Can you show how to compile this? Pin
JasonShort16-Mar-07 9:06
JasonShort16-Mar-07 9:06 
AnswerRe: Can you show how to compile this? Pin
JasonShort16-Mar-07 9:12
JasonShort16-Mar-07 9:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.