К GAC'у можно обратиться менеджером mscorcfg.dll через классы Microsoft.CLRAdmin. Этот вариант обращения к которому лежит здесь, но теперь рассмотрим собственно прямое обращение к неуправляемому коду, манипулирующему GAC'ом.
Вот такой вот код:
00001: Sub Main() 00002: 'System.Diagnostics.Process.Start("C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\gacutil.exe", "/l") 00003: 'Вместо вызова GacUtil манипулируем сборками в Гаке собственной интерфейсной библиотекой к Fusion.DLL 00004: 'Интерфейс ее описан тут - http://support.microsoft.com/default.aspx?scid=kb;en-us;317540 или тут ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.KB.v10.en/enu_kbnetframeworkkb/netframeworkkb/317540.htm 00005: Dim x As New fusion_dll.AssemblyCacheEnum(Nothing) 00006: Dim s1 As String = " " 00007: While s1 <> "" 00008: s1 = x.GetNextAssembly() 00009: Console.WriteLine(s1) 00010: End While 00011: Console.ReadLine() 00012: End SubВыдает мне при прогоне список всех моих 439 сборок:
На самом деле ситуация еще более запутанная, ибо GAC'а существует два типа (еще и тип ZAP) - Microsoft.CLRAdmin легко читает оба типа GAC'а. Можно это сделать и пямым обращением к неуправляему коду FUSION.DLL. Ну и вот собственно код управляемого Wrapper'а к неуправляемой библиотеке fusion.dll, сотворившей чудо на рисунках выше:
00001: Imports System.Runtime.InteropServices, System.Text 00002: 00003: <ComImport(), _ 00004: InterfaceType(ComInterfaceType.InterfaceIsIUnknown), _ 00005: Guid("e707dcde-d1cd-11d2-bab9-00c04f8eceae")> _ 00006: Interface IAssemblyCache 00007: 00008: <PreserveSig()> _ 00009: Function UninstallAssembly(ByVal flags As Integer, ByVal assemblyName As String, ByVal refData As InstallReference, ByRef disposition As AssemblyCacheUninstallDisposition) As Integer 00010: 00011: <PreserveSig()> _ 00012: Function QueryAssemblyInfo(ByVal flags As Integer, ByVal assemblyName As String, ByRef assemblyInfo As AssemblyInfo) As Integer 00013: 00014: <PreserveSig()> _ 00015: Function Reserved(ByVal flags As Integer, ByVal pvReserved As IntPtr, ByRef ppAsmItem As Object, ByVal assemblyName As String) As Integer 00016: 00017: <PreserveSig()> _ 00018: Function Reserved(ByRef ppAsmScavenger As Object) As Integer 00019: 00020: <PreserveSig()> _ 00021: Function InstallAssembly(ByVal flags As Integer, ByVal assemblyFilePath As String, ByVal refData As InstallReference) As Integer 00022: End Interface ' IAssemblyCache 00023: 00024: <ComImport(), _ 00025: InterfaceType(ComInterfaceType.InterfaceIsIUnknown), _ 00026: Guid("CD193BC0-B4BC-11d2-9833-00C04FC31D2E")> _ 00027: Interface IAssemblyName 00028: 00029: <PreserveSig()> _ 00030: Function SetProperty(ByVal PropertyId As Integer, ByVal pvProperty As IntPtr, ByVal cbProperty As Integer) As Integer 00031: 00032: <PreserveSig()> _ 00033: Function GetProperty(ByVal PropertyId As Integer, ByVal pvProperty As IntPtr, ByRef pcbProperty As Integer) As Integer 00034: 00035: <PreserveSig()> _ 00036: Function Finalize() As Integer 00037: 00038: <PreserveSig()> _ 00039: Function GetDisplayName(ByVal pDisplayName As StringBuilder, ByRef pccDisplayName As Integer, ByVal displayFlags As Integer) As Integer 00040: 00041: <PreserveSig()> _ 00042: Function Reserved(ByRef guid As Guid, ByVal obj1 As Object, ByVal obj2 As Object, ByVal string1 As String, ByVal llFlags As Int64, ByVal pvReserved As IntPtr, ByVal cbReserved As Integer, ByRef ppv As IntPtr) As Integer 00043: 00044: <PreserveSig()> _ 00045: Function GetName(ByRef pccBuffer As Integer, ByVal pwzName As StringBuilder) As Integer 00046: 00047: <PreserveSig()> _ 00048: Function GetVersion(ByRef versionHi As Integer, ByRef versionLow As Integer) As Integer 00049: 00050: <PreserveSig()> _ 00051: Function IsEqual(ByVal pAsmName As IAssemblyName, ByVal cmpFlags As Integer) As Integer 00052: 00053: <PreserveSig()> _ 00054: Function Clone(ByRef pAsmName As IAssemblyName) As Integer 00055: End Interface ' IAssemblyName 00056: 00057: <ComImport(), _ 00058: InterfaceType(ComInterfaceType.InterfaceIsIUnknown), _ 00059: Guid("21b8916c-f28e-11d2-a473-00c04f8ef448")> _ 00060: Interface IAssemblyEnum 00061: 00062: <PreserveSig()> _ 00063: Function GetNextAssembly(ByVal pvReserved As IntPtr, ByRef ppName As IAssemblyName, ByVal flags As Integer) As Integer 00064: 00065: <PreserveSig()> _ 00066: Function Reset() As Integer 00067: 00068: <PreserveSig()> _ 00069: Function Clone(ByRef ppEnum As IAssemblyEnum) As Integer 00070: End Interface ' IAssemblyEnum 00071: 00072: <ComImport(), _ 00073: InterfaceType(ComInterfaceType.InterfaceIsIUnknown), _ 00074: Guid("582dac66-e678-449f-aba6-6faaec8a9394")> _ 00075: Interface IInstallReferenceItem 00076: 00077: ' A pointer to a FUSION_INSTALL_REFERENCE structure. 00078: ' The memory is allocated by the GetReference method and is freed when 00079: ' IInstallReferenceItem is released. Callers must not hold a reference to this 00080: ' buffer after the IInstallReferenceItem object is released. 00081: ' This uses the InstallReferenceOutput object to avoid allocation 00082: ' issues with the interop layer. 00083: ' This cannot be marshaled directly - must use IntPtr 00084: <PreserveSig()> _ 00085: Function GetReference(ByRef pRefData As IntPtr, ByVal flags As Integer, ByVal pvReserced As IntPtr) As Integer 00086: End Interface ' IInstallReferenceItem 00087: 00088: <ComImport(), _ 00089: InterfaceType(ComInterfaceType.InterfaceIsIUnknown), _ 00090: Guid("56b1a988-7c0c-4aa2-8639-c3eb5a90226f")> _ 00091: Interface IInstallReferenceEnum 00092: 00093: <PreserveSig()> _ 00094: Function GetNextInstallReferenceItem(ByRef ppRefItem As IInstallReferenceItem, ByVal flags As Integer, ByVal pvReserced As IntPtr) As Integer 00095: End Interface ' IInstallReferenceEnum 00096: 00097: Public Enum AssemblyCommitFlags 00098: Default_ = 1 00099: Force = 2 00100: End Enum ' enum AssemblyCommitFlags 00101: 00102: Public Enum AssemblyCacheUninstallDisposition 00103: Unknown = 0 00104: Uninstalled = 1 00105: StillInUse = 2 00106: AlreadyUninstalled = 3 00107: DeletePending = 4 00108: HasInstallReference = 5 00109: ReferenceNotFound = 6 00110: End Enum 00111: 00112: <Flags()> _ 00113: Enum AssemblyCacheFlags 00114: GAC = 2 00115: End Enum 00116: 00117: Enum CreateAssemblyNameObjectFlags 00118: CANOF_DEFAULT = 0 00119: CANOF_PARSE_DISPLAY_NAME = 1 00120: End Enum 00121: 00122: <Flags()> _ 00123: Enum AssemblyNameDisplayFlags 00124: VERSION = 1 00125: CULTURE = 2 00126: PUBLIC_KEY_TOKEN = 4 00127: PROCESSORARCHITECTURE = 32 00128: RETARGETABLE = 128 00129: ALL = (VERSION _ 00130: Or (CULTURE _ 00131: Or (PUBLIC_KEY_TOKEN _ 00132: Or (PROCESSORARCHITECTURE Or RETARGETABLE)))) 00133: End Enum 00134: 00135: <StructLayout(LayoutKind.Sequential)> _ 00136: Public Class InstallReference 00137: 00138: Private cbSize As Integer 00139: Private flags As Integer 00140: Private a_guidScheme As Guid 00141: 00142: <MarshalAs(UnmanagedType.LPWStr)> _ 00143: Private a_identifier As String 00144: 00145: <MarshalAs(UnmanagedType.LPWStr)> _ 00146: Private a_description As String 00147: 00148: Public Sub New(ByVal guid As Guid, ByVal id As String, ByVal data As String) 00149: MyBase.New() 00150: cbSize = CType(((2 * IntPtr.Size) + (16 + ((id.Length + data.Length) * 2))), Integer) 00151: flags = 0 00152: ' quiet compiler warning 00153: If (flags = 0) Then 00154: 00155: End If 00156: a_guidScheme = guid 00157: a_identifier = id 00158: a_description = data 00159: End Sub 00160: 00161: Public ReadOnly Property GuidScheme() As Guid 00162: Get 00163: Return a_guidScheme 00164: End Get 00165: End Property 00166: 00167: Public ReadOnly Property Identifier() As String 00168: Get 00169: Return a_identifier 00170: End Get 00171: End Property 00172: 00173: Public ReadOnly Property Description() As String 00174: Get 00175: Return a_description 00176: End Get 00177: End Property 00178: End Class 00179: 00180: <StructLayout(LayoutKind.Sequential)> _ 00181: Structure AssemblyInfo 00182: 00183: Public cbAssemblyInfo As Integer ' size of this structure for future expansion 00184: Public assemblyFlags As Integer 00185: Public assemblySizeInKB As Long 00186: 00187: <MarshalAs(UnmanagedType.LPWStr)> _ 00188: Public currentAssemblyPath As String 00189: 00190: Public cchBuf As Integer 'size of path buf. 00191: End Structure 00192: 00193: <ComVisible(False)> _ 00194: Public Class InstallReferenceGuid 00195: 00196: Public Shared UninstallSubkeyGuid As Guid = New Guid("8cedc215-ac4b-488b-93c0-a50a49cb2fb8") 00197: Public Shared FilePathGuid As Guid = New Guid("b02f9d65-fb77-4f7a-afa5-b391309f11c9") 00198: Public Shared OpaqueGuid As Guid = New Guid("2ec93463-b0c3-45e1-8364-327e96aea856") 00199: ' these GUID cannot be used for installing into GAC. 00200: Public Shared MsiGuid As Guid = New Guid("25df0fc1-7f97-4070-add7-4b13bbfd7cb8") 00201: Public Shared OsInstallGuid As Guid = New Guid("d16d444c-56d8-11d5-882d-0080c847b195") 00202: 00203: Public Shared Function IsValidGuidScheme(ByVal guid As Guid) As Boolean 00204: Return (guid.Equals(UninstallSubkeyGuid) _ 00205: OrElse (guid.Equals(FilePathGuid) _ 00206: OrElse (guid.Equals(OpaqueGuid) OrElse guid.Equals(guid.Empty)))) 00207: End Function 00208: End Class 00209: 00210: <ComVisible(False)> _ 00211: Public Class AssemblyCache 00212: 00213: Public Shared Sub InstallAssembly(ByVal assemblyPath As String, ByVal reference As InstallReference, ByVal flags As AssemblyCommitFlags) 00214: If (Not (reference) Is Nothing) Then 00215: If Not InstallReferenceGuid.IsValidGuidScheme(reference.GuidScheme) Then 00216: Throw New ArgumentException("Invalid reference guid.", "guid") 00217: End If 00218: End If 00219: Dim ac As IAssemblyCache = Nothing 00220: Dim hr As Integer = 0 00221: hr = Utils.CreateAssemblyCache(ac, 0) 00222: If (hr >= 0) Then 00223: hr = ac.InstallAssembly(CType(flags, Integer), assemblyPath, reference) 00224: End If 00225: If (hr < 0) Then 00226: Marshal.ThrowExceptionForHR(hr) 00227: End If 00228: End Sub 00229: 00230: ' assemblyName has to be fully specified name. 00231: ' A.k.a, for v1.0/v1.1 assemblies, it should be "name, Version=xx, Culture=xx, PublicKeyToken=xx". 00232: ' For v2.0 assemblies, it should be "name, Version=xx, Culture=xx, PublicKeyToken=xx, ProcessorArchitecture=xx". 00233: ' If assemblyName is not fully specified, a random matching assembly will be uninstalled. 00234: Public Shared Sub UninstallAssembly(ByVal assemblyName As String, ByVal reference As InstallReference, ByRef disp As AssemblyCacheUninstallDisposition) 00235: Dim dispResult As AssemblyCacheUninstallDisposition = AssemblyCacheUninstallDisposition.Uninstalled 00236: If (Not (reference) Is Nothing) Then 00237: If Not InstallReferenceGuid.IsValidGuidScheme(reference.GuidScheme) Then 00238: Throw New ArgumentException("Invalid reference guid.", "guid") 00239: End If 00240: End If 00241: Dim ac As IAssemblyCache = Nothing 00242: Dim hr As Integer = Utils.CreateAssemblyCache(ac, 0) 00243: If (hr >= 0) Then 00244: hr = ac.UninstallAssembly(0, assemblyName, reference, dispResult) 00245: End If 00246: If (hr < 0) Then 00247: Marshal.ThrowExceptionForHR(hr) 00248: End If 00249: disp = dispResult 00250: End Sub 00251: 00252: ' See comments in UninstallAssembly 00253: Public Shared Function QueryAssemblyInfo(ByVal assemblyName As String) As String 00254: If (assemblyName = Nothing) Then 00255: Throw New ArgumentException("Invalid name", "assemblyName") 00256: End If 00257: Dim aInfo As AssemblyInfo = New AssemblyInfo 00258: aInfo.cchBuf = 1024 00259: ' Get a string with the desired length 00260: aInfo.currentAssemblyPath = New String(Microsoft.VisualBasic.ChrW(92), aInfo.cchBuf) 00261: Dim ac As IAssemblyCache = Nothing 00262: Dim hr As Integer = Utils.CreateAssemblyCache(ac, 0) 00263: If (hr >= 0) Then 00264: hr = ac.QueryAssemblyInfo(0, assemblyName, aInfo) 00265: End If 00266: If (hr < 0) Then 00267: Marshal.ThrowExceptionForHR(hr) 00268: End If 00269: Return aInfo.currentAssemblyPath 00270: End Function 00271: End Class 00272: 00273: <ComVisible(False)> _ 00274: Public Class AssemblyCacheEnum 00275: 00276: Private m_AssemblyEnum As IAssemblyEnum = Nothing 00277: Private done As Boolean 00278: 00279: ' null means enumerate all the assemblies 00280: Public Sub New(ByVal assemblyName As String) 00281: MyBase.New() 00282: Dim fusionName As IAssemblyName = Nothing 00283: Dim hr As Integer = 0 00284: If (Not (assemblyName) Is Nothing) Then 00285: hr = Utils.CreateAssemblyNameObject(fusionName, assemblyName, CreateAssemblyNameObjectFlags.CANOF_PARSE_DISPLAY_NAME, IntPtr.Zero) 00286: End If 00287: If (hr >= 0) Then 00288: hr = Utils.CreateAssemblyEnum(m_AssemblyEnum, IntPtr.Zero, fusionName, AssemblyCacheFlags.GAC, IntPtr.Zero) 00289: End If 00290: If (hr < 0) Then 00291: Marshal.ThrowExceptionForHR(hr) 00292: End If 00293: End Sub 00294: 00295: Public Function GetNextAssembly() As String 00296: Dim hr As Integer = 0 00297: Dim fusionName As IAssemblyName = Nothing 00298: If done Then 00299: Return Nothing 00300: End If 00301: ' Now get next IAssemblyName from m_AssemblyEnum 00302: hr = m_AssemblyEnum.GetNextAssembly(CType(0, IntPtr), fusionName, 0) 00303: If (hr < 0) Then 00304: Marshal.ThrowExceptionForHR(hr) 00305: End If 00306: If (Not (fusionName) Is Nothing) Then 00307: Return GetFullName(fusionName) 00308: Else 00309: done = True 00310: Return Nothing 00311: End If 00312: End Function 00313: 00314: Private Function GetFullName(ByVal fusionAsmName As IAssemblyName) As String 00315: Dim sDisplayName As StringBuilder = New StringBuilder(1024) 00316: Dim iLen As Integer = 1024 00317: Dim hr As Integer = fusionAsmName.GetDisplayName(sDisplayName, iLen, CType(AssemblyNameDisplayFlags.ALL, Integer)) 00318: If (hr < 0) Then 00319: Marshal.ThrowExceptionForHR(hr) 00320: End If 00321: Return sDisplayName.ToString 00322: End Function 00323: End Class 00324: 00325: ' class AssemblyCacheEnum 00326: Public Class AssemblyCacheInstallReferenceEnum 00327: 00328: Private refEnum As IInstallReferenceEnum 00329: 00330: Public Sub New(ByVal assemblyName As String) 00331: MyBase.New() 00332: Dim fusionName As IAssemblyName = Nothing 00333: Dim hr As Integer = Utils.CreateAssemblyNameObject(fusionName, assemblyName, CreateAssemblyNameObjectFlags.CANOF_PARSE_DISPLAY_NAME, IntPtr.Zero) 00334: If (hr >= 0) Then 00335: hr = Utils.CreateInstallReferenceEnum(refEnum, fusionName, 0, IntPtr.Zero) 00336: End If 00337: If (hr < 0) Then 00338: Marshal.ThrowExceptionForHR(hr) 00339: End If 00340: End Sub 00341: 00342: Public Function GetNextReference() As InstallReference 00343: Dim item As IInstallReferenceItem = Nothing 00344: Dim hr As Integer = refEnum.GetNextInstallReferenceItem(item, 0, IntPtr.Zero) 00345: If (CType(hr, UInteger) = -2147024637) Then 00346: ' ERROR_NO_MORE_ITEMS 00347: Return Nothing 00348: End If 00349: If (hr < 0) Then 00350: Marshal.ThrowExceptionForHR(hr) 00351: End If 00352: Dim refData As IntPtr 00353: Dim instRef As InstallReference = New InstallReference(Guid.Empty, String.Empty, String.Empty) 00354: hr = item.GetReference(refData, 0, IntPtr.Zero) 00355: If (hr < 0) Then 00356: Marshal.ThrowExceptionForHR(hr) 00357: End If 00358: Marshal.PtrToStructure(refData, instRef) 00359: Return instRef 00360: End Function 00361: End Class 00362: 00363: Class Utils 00364: Friend Declare Function CreateAssemblyEnum Lib "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\fusion.dll" (ByRef ppEnum As IAssemblyEnum, ByVal pUnkReserved As IntPtr, ByVal pName As IAssemblyName, ByVal flags As AssemblyCacheFlags, ByVal pvReserved As IntPtr) As Integer 00365: Friend Declare Function CreateAssemblyNameObject Lib "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\fusion.dll" (ByRef ppAssemblyNameObj As IAssemblyName, ByVal szAssemblyName As String, ByVal flags As CreateAssemblyNameObjectFlags, ByVal pvReserved As IntPtr) As Integer 00366: Friend Declare Function CreateAssemblyCache Lib "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\fusion.dll" (ByRef ppAsmCache As IAssemblyCache, ByVal reserved As Integer) As Integer 00367: Friend Declare Function CreateInstallReferenceEnum Lib "C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\fusion.dll" (ByRef ppRefEnum As IInstallReferenceEnum, ByVal pName As IAssemblyName, ByVal dwFlags As Integer, ByVal pvReserved As IntPtr) As Integer 00368: End Class
Comments (
)
<00>
<01>
<02>
<03>
<04>
<05>
<06>
<07>
<08>
<09>
<10>
<11>
<12>
<13>
<14>
<15>
<16>
<17>
<18>
<19>
<20>
<21>
<22>
<23>
Link to this page:
//www.vb-net.com/windows/WinDump/FusionWrapper_VB.htm
<SITEMAP> <MVC> <ASP> <NET> <DATA> <KIOSK> <FLEX> <SQL> <NOTES> <LINUX> <MONO> <FREEWARE> <DOCS> <ENG> <CHAT ME> <ABOUT ME> < THANKS ME> |