GAC API 接口

简介

GAC (全局程序集缓存) 可以安装在Windows上的程序集中央存储库,它提供了强大的程序集实现了版本统一和安全访问。 本文给出了使用GAC的一些方法。GAC 的内部结构在MSDN文档中或许并没有论述,但是它的文件系统结构 (e.g. C:\WINDOWS\assembly) 似乎更直观的能让我们得以了解。这里有一个用COM API来访问GAC的方法,它就是 Fusion API,因为它是由 fusion.dll 来实现的。

背景

这项工作的基础是一篇关于 GAC API 的微软知识库文章 DOC: Global Assembly Cache (GAC) APIs Are Not Documented in the .NET Framework Software Development Kit (SDK) Documentation。这篇文章详细解释了在fusion.dll中使用 GAC API 的方法。这个DLL 包含了一些 API 调用以实现 COM 与 各种相关 GAC 空间的功能。 比如添加或者删除一些组件, 枚举已安装的组件等。 我们在这里所做的只是简单的调用这个 API 和COM 接口(C# & adorn) 代码是前面提到的微软知识库中的部分代码。

 

另外一种使用 API的方式取决于GAC API 中的 .NET framework. 显然 .NET framework 有权访问 GAC,即使这个权限没有被提及. CodeProject 上面 Article "Undocumented Fusion" <John Renaud>很好的描述了怎样通过反射很好的使用它们. 这篇文章还很有见地的描述了 API (比如一些例子的来历), 我们只是简单地给出 fusion.dll API 希望大家以 Johns 文章为附加的背景资料。

代码

第一步,我们需要详读上面给出链接的那篇文章,它将是你明确你需要 API 的那一部分。 我们给出的这些例子在这篇文章中我们主要探究 GAC已安装的组件要说明的是,你应该熟悉COM. 看下面这个类:

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.

IAssemblyEnum ae = AssemblyCache.CreateGACEnum();

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

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.

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.

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-functionGetProperty which uses a variant type for returning values:

[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 classSystem.Runtime.InteropServices.Marshal is of great service here:

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;
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(api)