2009-10-21 23 views
11

¿Cómo puedo enumerar todos los conjuntos disponibles en GAC en C#?enumerando conjuntos en GAC

Actualmente estoy enfrentando un problema con un código estúpido: el ensamblado llamado Telerik.Web.UI.dll se refiere y se usa en el proyecto; esta DLL particular no está presente en la carpeta BIN. Y la aplicación funciona bien en el servidor, pero en mi máquina, obviamente el compilador está dando error. Ex-Developer insiste en que no está en GAC en el servidor y 'es lo que es'. Ahora necesito verificar si esta DLL está registrada en GAC o no.

La ayuda será apreciada.

Buen día;

+0

@effkey - ¿Has logrado solucionar este problema? – Kev

+0

nop; Yo no era capaz de; más bien descargué los archivos .dll de torrents (misma versión) y funcionó. Todavía no entiendo de dónde ASP .NET está recogiendo DLLz si no están en GAC. – effkay

Respuesta

10

Si usted tiene acceso limitado al servidor, entonces esto podría funcionar:

// List of all the different types of GAC folders for both 32bit and 64bit 
// environments. 
List<string> gacFolders = new List<string>() { 
    "GAC", "GAC_32", "GAC_64", "GAC_MSIL", 
    "NativeImages_v2.0.50727_32", 
    "NativeImages_v2.0.50727_64", 
    "NativeImages_v4.0.30319_32", 
    "NativeImages_v4.0.30319_64" 
}; 

foreach (string folder in gacFolders) 
{ 
    string path = Path.Combine(
     Environment.ExpandEnvironmentVariables(@"%systemroot%\assembly"), 
     folder); 

    if(Directory.Exists(path)) 
    { 
     Response.Write("<hr/>" + folder + "<hr/>"); 

     string[] assemblyFolders = Directory.GetDirectories(path); 
     foreach (string assemblyFolder in assemblyFolders) 
     { 
      Response.Write(assemblyFolder + "<br/>"); 
     } 
    } 
} 

Básicamente enumera las carpetas GAC primas. Funciona en el alojamiento compartido de DiscountASP, por lo que podría funcionar para su entorno de alojamiento.

Podría embellecerse enumerando cada vez más en la carpeta de cada ensamblaje para extraer el número de versión y el token de clave pública.

4

Consulte este artículo codeproject GAC API Interface. Esto usa fusion.dll no documentado para enumurar el GAC. Pero el autor afirma que

Se sabe que este código funciona con .NET 1.1 y 2.0. Tenga en cuenta que el DLL fusion.dll es diferente en 1.1 y 2.0. Entonces, si tiene ambos marcos instalados, asegúrese de señalar el código a la DLL correcta. De lo contrario, la mayoría de las llamadas a la API fallarán. La implementación predeterminada utiliza la que se encuentra en en el directorio WINDOWS.

+0

gracias - comprobará; pero me temo que podría crear un problema con los permisos; ya que tengo acceso limitado al servidor, y dudo de su funcionalidad bajo el usuario de ASP NET. pero gracias de todos modos; Lo vi antes también, pero descarté la duda. Pero déjame probarlo. – effkay

+1

No está indocumentado. Al menos ya no. https://support.microsoft.com/kb/317540 o http://msdn.microsoft.com/en-us/library/ms404523.aspx –

4

Realmente no necesita escribir algo en C# para averiguar si este dll específico está en el gac. Puede usar gacutil.exe con la opción/l desde la línea de comando para mostrar el contenido del GAC.

+0

ojalá pudiera - Tengo acceso limitado al servidor - es decir, Solo FTP :) pero aún así, gracias por el comentario – effkay

+0

@effkay - lo siento, no fue útil. Si tiene acceso limitado al servidor, ¿cómo ayudará una solución de código? –

+0

@MikeTwo Parece que planea subir una página web que enumerará qué ensamblajes hay en el GAC. – BrainSlugs83

-3

Puede ser que necesite GAC espectador algo como esto:

alt text

Video: How to use Add GAC References Dialog

Esperanza esto ayuda

s

+0

Eso no ayudará ya que dijo que solo tiene acceso FTP al servidor. Quiere poder enumerar el GAC usando el código C# que se ejecuta en un entorno que no sea de confianza total. – BrainSlugs83

3

Si se trata de Plain Jane sitio ASP.NET, y el ensamblaje no se encuentra en la carpeta bin del sitio ni en el GAC del servidor (y no hay nada sospechoso en el archivo web.config), quizás el sitio es un sub-sitio de algún tipo y uno de los más arriba del sitio contiene la referencia en la carpeta bin (o algo sospechoso en su web.config, ya que los sub-sitios/carpetas heredan los archivos web.configs de sus padres) ?

Ahora, si tiene un entorno donde el archivo se está cargando correctamente (y suena como lo hace), puede simplemente preguntar a .NET dónde.DLL está viniendo y mostrar que en lugar, por ejemplo:

Assembly a = Assembly.Load("Microsoft.VisualStudio.Shell, Version=2.0.0.0, " 
      + "PublicKeyToken=b03f5f7f11d50a3a, Culture=Neutral"); 

Console.WriteLine(a.Location); 

cargará una asamblea y mostrar su ubicación en el disco, mi salida es: C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.Shell\2.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Shell.dll

Si es en "C: \ Windows \ Asamblea \ "usted sabe que está en el GAC.

También puede hacer esto sin una llamada Assembly.Load si ya hace referencia al ensamblado puede enumerar los ensamblados cargados en el app.dominio actual y simplemente imprimir (o renderizar a un control literal, o Response.Write, etc ...) cuáles son sus propiedades de .Location.

Editar: El código para que se ve algo como esto:

foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) 
{ 
    Console.WriteLine(a.GetName().FullName); 
    Console.WriteLine(a.Location); 
    Console.WriteLine(); 
} 

Editar: En un entorno de plena confianza, el siguiente código (aplicación de consola) enumerará el GAC y escribir cada ensamblaje, debería ser fácil modificarlo en una aplicación ASP.NET, pero no estoy seguro de si funcionará en un entorno que no sea confiable (solo adivine aquí, puede tener suerte):

static void ProcessFile(string file) 
{ 
    try 
    { 
     Assembly a = Assembly.LoadFile(file); 

     Console.WriteLine(a.GetName().FullName); 
    } 
    catch { /* do nothing */ } 
} 

static void ProcessFolder(string folder) 
{ 
    foreach (string file in Directory.GetFiles(folder)) 
    { 
     ProcessFile(file); 
    } 

    foreach (string subFolder in Directory.GetDirectories(folder)) 
    { 
     ProcessFolder(subFolder); 
    } 
} 

static void Main(string[] args) 
{ 
    ProcessFolder(@"C:\Windows\Assembly"); 
} 
3

un método simple para enumerar los archivos DLL en un directorio

public static string[] GetGlobalAssemblyCacheFiles(string path) 
{ 
    List<string> files = new List<string>(); 

    DirectoryInfo di = new DirectoryInfo(path); 

    foreach (FileInfo fi in di.GetFiles("*.dll")) 
    { 
     files.Add(fi.FullName); 
    } 

    foreach (DirectoryInfo diChild in di.GetDirectories()) 
    { 
     var files2 = GetGlobalAssemblyCacheFiles(diChild.FullName); 
     files.AddRange(files2); 
    } 

    return files.ToArray(); 
} 

y usted puede conseguir todos los archivos

string gacPath = Environment.GetFolderPath(System.Environment.SpecialFolder.Windows) + "\\assembly"; 
var files = GetGlobalAssemblyCacheFiles(gacPath); 

Si necesita cargar cada conjunto, se obtiene una excepción para los diferentes tiempo de ejecución versión. Por este motivo, puede cargar el ensamblaje con Assembly.ReflectionOnlyLoadFrom para cargar el ensamblaje solo en modo reflejo. Entonces, Assembly no se carga en su AppDomain y no lanza una excepción.

1

figura que bien podría lanzar en mi solución basada LINQ (muy útil si su sólo en busca de un solo archivo y no quieren para enumerar todos los archivos)

función para buscar los archivos:

public static IEnumerable<string> FindFiles (string path, string filter = "", int depth = int.MaxValue) { 
     DirectoryInfo di = new DirectoryInfo(path); 

     IEnumerable<string> results = (! string.IsNullOrEmpty(filter) ? di.GetFiles(filter) : di.GetFiles()).Select(f => f.FullName); 
     if (depth > 0) { 
      results = results.Concat(di.GetDirectories().SelectMany(d => FindFiles(d.FullName, filter, depth - 1))); 
     } 

     return results; 
    } 

Y para llamar (i no tenía Environment.SpecialFolder.Windows utiliza con tal fin Environment.SpecialFolder.System lugar)

string path = Environment.GetFolderPath(Environment.SpecialFolder.System) + "\\..\\assembly"; 
foreach (string s in FindFiles(path, "*.dll")) { 
    Console.WriteLine(s); 
} 

Además, como FYI este método enume clasifica todo el GAC y puede encontrar archivos DLL duplicados en tmp/y temp /, Tmp se utiliza para la instalación y Temp se utiliza para la desinstalación.