【转】Sample Managed GAC API Wrappers
//-------------------------------------------------------------
//  GACWrap.cs
//
// This implements managed wrappers to GAC API  Interfaces
//-------------------------------------------------------------
using System;
using System.Runtime.InteropServices;
using  System.Text;
namespace System.GACManagedAccess
{
     //-------------------------------------------------------------
    //  Interfaces defined by fusion
     //-------------------------------------------------------------
     [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),  Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")]
    internal interface  IAssemblyCache
    {
        [PreserveSig()]
        int  UninstallAssembly(
                            int  flags,
                             [MarshalAs(UnmanagedType.LPWStr)]
                            String  assemblyName,
                            InstallReference  refData,
                            out AssemblyCacheUninstallDisposition  disposition);
       
        [PreserveSig()]
        int  QueryAssemblyInfo(
                            int  flags,
                             [MarshalAs(UnmanagedType.LPWStr)]
                            String  assemblyName,
                            ref AssemblyInfo  assemblyInfo);
        [PreserveSig()]
        int Reserved         (
                            int flags,
                             IntPtr pvReserved,
                            out Object  ppAsmItem,
                             [MarshalAs(UnmanagedType.LPWStr)]
                            String  assemblyName);
        [PreserveSig()]
        int Reserved(out Object  ppAsmScavenger);
       
        [PreserveSig()]
        int  InstallAssembly(
                            int  flags,
                             [MarshalAs(UnmanagedType.LPWStr)]
                            String  assemblyFilePath,
                            InstallReference  refData);
    }// IAssemblyCache
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),  Guid("CD193BC0-B4BC-11d2-9833-00C04FC31D2E")]
    internal interface  IAssemblyName
    {
        [PreserveSig()]
        int  SetProperty(
                int PropertyId,
                IntPtr  pvProperty,
                int cbProperty);
       
         [PreserveSig()]
        int GetProperty(
                int  PropertyId,
                IntPtr pvProperty,
                ref int  pcbProperty);
        [PreserveSig()]
        int Finalize();
       
         [PreserveSig()]
        int GetDisplayName(
                StringBuilder  pDisplayName,
                ref int pccDisplayName,
                int  displayFlags);
       
        [PreserveSig()]
        int Reserved(ref  Guid guid,
            Object obj1,
            Object  obj2,
            String string1,
            Int64  llFlags,
            IntPtr pvReserved,
            int  cbReserved,
            out IntPtr ppv);
        [PreserveSig()]
        int GetName(
                ref int  pccBuffer,
                StringBuilder pwzName);
        [PreserveSig()]
        int GetVersion(
                out int  versionHi,
                out int versionLow);
         [PreserveSig()]
        int IsEqual(
                IAssemblyName  pAsmName,
                int cmpFlags);
        [PreserveSig()]
        int Clone(out IAssemblyName  pAsmName);
    }// IAssemblyName
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),  Guid("21b8916c-f28e-11d2-a473-00c04f8ef448")]
    internal interface  IAssemblyEnum
    {
        [PreserveSig()]
        int  GetNextAssembly(
                IntPtr pvReserved,
                out  IAssemblyName ppName,
                int flags);
         [PreserveSig()]
        int Reset();
        [PreserveSig()]
         int Clone(out IAssemblyEnum ppEnum);
    }// IAssemblyEnum
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),  Guid("582dac66-e678-449f-aba6-6faaec8a9394")]
    internal interface  IInstallReferenceItem
    {
        // A pointer to a  FUSION_INSTALL_REFERENCE structure. 
        // The memory is allocated by  the GetReference method and is freed when 
        // IInstallReferenceItem  is released. Callers must not hold a reference to this 
        // buffer  after the IInstallReferenceItem object is released. 
        // This uses the  InstallReferenceOutput object to avoid allocation 
        // issues with the  interop layer. 
        // This cannot be marshaled directly - must use  IntPtr 
        [PreserveSig()]
        int  GetReference(
                out IntPtr pRefData, 
                int  flags, 
                IntPtr pvReserced);
    }//  IInstallReferenceItem
    [ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown),  Guid("56b1a988-7c0c-4aa2-8639-c3eb5a90226f")]
    internal interface  IInstallReferenceEnum
    {
        [PreserveSig()]
        int  GetNextInstallReferenceItem(
                out IInstallReferenceItem  ppRefItem, 
                int flags, 
                IntPtr  pvReserced);
    }// IInstallReferenceEnum
    public enum AssemblyCommitFlags
    {
        Default          =  1,
        Force            = 2
    }// enum AssemblyCommitFlags
    public enum AssemblyCacheUninstallDisposition
    {
         Unknown                 = 0,
        Uninstalled             = 1,
         StillInUse              = 2,
        AlreadyUninstalled      = 3,
         DeletePending           = 4,
        HasInstallReference     = 5,
         ReferenceNotFound       = 6
    }
   
    [Flags]
    internal enum  AssemblyCacheFlags
    {
        GAC          = 2,
    }
    internal enum CreateAssemblyNameObjectFlags
    {
         CANOF_DEFAULT            = 0,
        CANOF_PARSE_DISPLAY_NAME = 1,
     }
 
    [Flags]
    internal enum AssemblyNameDisplayFlags
    {   
        VERSION                   = 0x01,
         CULTURE                   = 0x02,
        PUBLIC_KEY_TOKEN          =  0x04,
        PROCESSORARCHITECTURE     = 0x20,
         RETARGETABLE              = 0x80,
        // This enum will change in the  future to include
        // more attributes.
         ALL                       = VERSION
                                    |  CULTURE
                                    |  PUBLIC_KEY_TOKEN
                                    |  PROCESSORARCHITECTURE
                                    |  RETARGETABLE
    }
   
    [StructLayout(LayoutKind.Sequential)]
     public class InstallReference
    {
        public InstallReference(Guid  guid, String id, String data)
        {
            cbSize =  (int)(2*IntPtr.Size+16+(id.Length+data.Length)*2);
            flags =  0;
            // quiet compiler warning 
            if (flags == 0) {  }
            guidScheme = guid;
            identifier =  id;
            description = data;
        }
        public Guid GuidScheme
        {
            get { return  guidScheme;}
        }
        public String Identifier
        {
            get { return  identifier; }
        }
        public String Description
        {
            get { return  description;}
        }
        int         cbSize;
        int         flags;
         Guid        guidScheme;
        [MarshalAs(UnmanagedType.LPWStr)]
         String      identifier;
        [MarshalAs(UnmanagedType.LPWStr)]
         String      description;
    }
    [StructLayout(LayoutKind.Sequential)]
    internal struct  AssemblyInfo
    {
        public int      cbAssemblyInfo; // size of this  structure for future expansion
        public int       assemblyFlags;
        public long     assemblySizeInKB;
         [MarshalAs(UnmanagedType.LPWStr)]
        public String    currentAssemblyPath;
        public int      cchBuf; // size of path  buf.
    }
    [ComVisible(false)]
    public class InstallReferenceGuid
     {
        public static bool IsValidGuidScheme(Guid guid)
         {
            return (guid.Equals(UninstallSubkeyGuid)     ||
                    guid.Equals(FilePathGuid)            ||
                    guid.Equals(OpaqueGuid)        ||
                    guid.Equals(Guid.Empty));
        }
   
        public readonly static Guid UninstallSubkeyGuid  = new  Guid("8cedc215-ac4b-488b-93c0-a50a49cb2fb8");
        public readonly static  Guid FilePathGuid         = new  Guid("b02f9d65-fb77-4f7a-afa5-b391309f11c9");
        public readonly static  Guid OpaqueGuid           = new  Guid("2ec93463-b0c3-45e1-8364-327e96aea856");
        // these GUID cannot be  used for installing into GAC.
        public readonly static Guid  MsiGuid              = new  Guid("25df0fc1-7f97-4070-add7-4b13bbfd7cb8");
        public readonly static  Guid OsInstallGuid        = new Guid("d16d444c-56d8-11d5-882d-0080c847b195");    
    }
    [ComVisible(false)]
    public static class AssemblyCache
     {
        public static void InstallAssembly(String assemblyPath,  InstallReference reference, AssemblyCommitFlags flags)
         {
            if (reference != null) {
                if  (!InstallReferenceGuid.IsValidGuidScheme(reference.GuidScheme))
                     throw new ArgumentException("Invalid reference guid.", "guid");
             }
IAssemblyCache ac = null;
            int hr = 0;
     
            hr =  Utils.CreateAssemblyCache(out ac, 0);
            if (hr >= 0)  {
                hr = ac.InstallAssembly((int)flags, assemblyPath,  reference);
            }
            if (hr < 0) {
                 Marshal.ThrowExceptionForHR(hr);
            }
        }
        // assemblyName has to be fully specified name. 
        // A.k.a,  for v1.0/v1.1 assemblies, it should be "name, Version=xx, Culture=xx,  PublicKeyToken=xx".
        // For v2.0 assemblies, it should be "name,  Version=xx, Culture=xx, PublicKeyToken=xx, ProcessorArchitecture=xx".
         // If assemblyName is not fully specified, a random matching assembly will be  uninstalled. 
        public static void UninstallAssembly(String  assemblyName, InstallReference reference, out AssemblyCacheUninstallDisposition  disp)
        {
            AssemblyCacheUninstallDisposition dispResult =  AssemblyCacheUninstallDisposition.Uninstalled;
            if (reference !=  null) {
                if  (!InstallReferenceGuid.IsValidGuidScheme(reference.GuidScheme))
                     throw new ArgumentException("Invalid reference guid.", "guid");
             }
           
            IAssemblyCache ac = null;  
      
            int hr = Utils.CreateAssemblyCache(out ac, 0);
            if  (hr >= 0) {
                hr = ac.UninstallAssembly(0, assemblyName,  reference, out dispResult);
            }
            if (hr < 0) {
                 Marshal.ThrowExceptionForHR(hr);
            }
            disp = dispResult;
        }
        // See comments in UninstallAssembly
        public static String  QueryAssemblyInfo(String assemblyName)
        {
            if  (assemblyName == null) {
                throw new ArgumentException("Invalid  name", "assemblyName");
            }
AssemblyInfo aInfo = new AssemblyInfo();
            aInfo.cchBuf = 1024;
            // Get a string with the  desired length
            aInfo.currentAssemblyPath = new String('\0',  aInfo.cchBuf) ;
            IAssemblyCache ac = null;
            int hr =  Utils.CreateAssemblyCache(out ac, 0);
            if (hr >= 0)  {
                hr = ac.QueryAssemblyInfo(0, assemblyName, ref  aInfo);
            }
            if (hr < 0) {
                 Marshal.ThrowExceptionForHR(hr);
            }
            return aInfo.currentAssemblyPath;
        }
    }
    [ComVisible(false)]
    public class AssemblyCacheEnum
     {
        // null means enumerate all the assemblies
        public  AssemblyCacheEnum(String assemblyName)
        {
            IAssemblyName  fusionName = null;
            int hr = 0;
            if (assemblyName != null) {
                hr =  Utils.CreateAssemblyNameObject(
                        out  fusionName,
                        assemblyName,
                         CreateAssemblyNameObjectFlags.CANOF_PARSE_DISPLAY_NAME,
                         IntPtr.Zero);
            }
            if (hr >= 0) {
                hr =  Utils.CreateAssemblyEnum(
                        out  m_AssemblyEnum,
                         IntPtr.Zero,
                        fusionName,
                         AssemblyCacheFlags.GAC,
                        IntPtr.Zero);
             }
            if (hr < 0) {
                 Marshal.ThrowExceptionForHR(hr);
            }
        }
        public String GetNextAssembly()
        {
            int hr =  0;
            IAssemblyName fusionName = null;
            if (done) {
                return null;
             }
     
            // Now get next IAssemblyName from  m_AssemblyEnum
            hr = m_AssemblyEnum.GetNextAssembly((IntPtr) 0,  out fusionName, 0);
            if (hr < 0) {
                 Marshal.ThrowExceptionForHR(hr);
            }
            if (fusionName != null) {
                return  GetFullName(fusionName);
            }
            else  {
                done = true;
                return null;
             }
        }
   
        private String GetFullName(IAssemblyName  fusionAsmName)
        {
            StringBuilder sDisplayName = new  StringBuilder(1024);
            int iLen = 1024;
            
            int hr = fusionAsmName.GetDisplayName(sDisplayName, ref iLen,  (int)AssemblyNameDisplayFlags.ALL);
            if (hr < 0)  {
                Marshal.ThrowExceptionForHR(hr);
            }
            return sDisplayName.ToString();
        }
        private IAssemblyEnum m_AssemblyEnum = null;
        private bool  done;
    }// class AssemblyCacheEnum
    public class AssemblyCacheInstallReferenceEnum
    {
        public  AssemblyCacheInstallReferenceEnum(String assemblyName)
         {
            IAssemblyName fusionName = null;
            int hr =  Utils.CreateAssemblyNameObject(
                        out fusionName,  
                        assemblyName, 
                         CreateAssemblyNameObjectFlags.CANOF_PARSE_DISPLAY_NAME,
                         IntPtr.Zero);
            if (hr >= 0) {
                hr =  Utils.CreateInstallReferenceEnum(out refEnum, fusionName, 0,  IntPtr.Zero);
            }
            if (hr < 0) {
                 Marshal.ThrowExceptionForHR(hr);
            }
        }
        public InstallReference GetNextReference()
         {
            IInstallReferenceItem item = null;
            int hr =  refEnum.GetNextInstallReferenceItem(out item, 0, IntPtr.Zero);
            if  ((uint)hr == 0x80070103) {   // ERROR_NO_MORE_ITEMS
                return  null;
            }
            if (hr < 0) { 
                 Marshal.ThrowExceptionForHR(hr);
            }
            IntPtr refData; 
            InstallReference instRef = new  InstallReference(Guid.Empty, String.Empty, String.Empty);
            hr = item.GetReference(out refData, 0,  IntPtr.Zero);
            if (hr < 0) {
                 Marshal.ThrowExceptionForHR(hr);
            }
            Marshal.PtrToStructure(refData, instRef); 
            return  instRef;
        }
        private IInstallReferenceEnum refEnum;
    }
    internal class Utils
    {
         [DllImport("fusion.dll")]
        internal static extern int  CreateAssemblyEnum(
                out IAssemblyEnum ppEnum,  
                IntPtr pUnkReserved, 
                IAssemblyName  pName, 
                AssemblyCacheFlags flags, 
                IntPtr  pvReserved);
        [DllImport("fusion.dll")]
        internal static extern int  CreateAssemblyNameObject(
                out IAssemblyName  ppAssemblyNameObj, 
                 [MarshalAs(UnmanagedType.LPWStr)]
                String szAssemblyName,  
                CreateAssemblyNameObjectFlags flags, 
                 IntPtr pvReserved);
        [DllImport("fusion.dll")]
        internal static extern int  CreateAssemblyCache(
                out IAssemblyCache ppAsmCache,  
                int reserved);
        [DllImport("fusion.dll")]
        internal static extern int  CreateInstallReferenceEnum(
                out IInstallReferenceEnum  ppRefEnum, 
                IAssemblyName pName, 
                int  dwFlags, 
                IntPtr pvReserved);      
    } 
}
<update date="2004/9/28"> Add enumeration of install reference to managed GAC API wrappers. And Add comments to UninstallAssembly behavior. </update>
 
                    
                
 
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号