2009-10-21 6 views
11

Comment puis-je énumérer tous les assemblys disponibles dans GAC en C#?énumération des assemblages dans GAC

En fait, je suis confronté à un problème avec un code stupide - l'assembly appelé Telerik.Web.UI.dll est référencé et utilisé dans le projet - cette DLL particulière n'est pas présente dans le dossier BIN. Et l'application fonctionne bien sur le serveur - mais sur ma machine, évidemment le compilateur donne une erreur. Ex-Developer insiste sur le fait qu'il n'est pas dans GAC sur le serveur et «c'est ce qu'il est». Maintenant, j'ai besoin de vérifier si cette DLL est enregistrée dans GAC ou non.

Une aide sera appréciée.

Bonne journée;

+0

@effkey - avez-vous réussi à résoudre ce problème? – Kev

+0

nop; Je n'étais pas capable de; J'ai plutôt téléchargé les fichiers .dll à partir de torrents (même version) et ils ont fonctionné. Je ne comprends toujours pas d'où ASP .NET ramasse le DLLz s'ils ne sont pas dans le GAC. – effkay

Répondre

10

Si vous avez un accès limité au serveur, cela pourrait fonctionner:

// 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/>"); 
     } 
    } 
} 

Il énumère essentiellement les dossiers bruts GAC. Cela fonctionne sur l'hébergement partagé DiscountASP, donc cela pourrait fonctionner pour votre environnement d'hébergement.

Il pourrait être embelli en énumérant plus en profondeur dans le dossier de chaque assemblée pour retirer le numéro de version et le jeton de clé publique.

4

Cochez cet article codeproject GAC API Interface. Cela utilise fusion.dll non documenté pour énumérer le GAC. Mais l'auteur prétend que

Ce code est connu pour fonctionner avec .NET 1.1 et 2.0. S'il vous plaît noter que la DLL fusion.dll est différente dans 1.1 et 2.0. Donc si vous avez les deux frameworks installés, assurez-vous de pointer le code vers la bonne DLL. Autrement, la plupart des appels API échoueront. L'implémentation par défaut utilise celle qui se trouve dans le répertoire WINDOWS.

+0

merci - va vérifier; mais j'ai peur qu'il pourrait créer un problème avec les autorisations; car j'ai un accès limité au serveur - et je doute de sa fonctionnalité sous ASP NET User. mais merci quand même; Je l'ai vu plus tôt aussi, mais exclu parce que plus de doute. Mais laissez-moi essayer. – effkay

+1

Ce n'est pas non documenté. Au moins pas plus. https://support.microsoft.com/kb/317540 ou http://msdn.microsoft.com/en-us/library/ms404523.aspx –

4

Vous n'avez pas vraiment besoin d'écrire quelque chose en C# pour savoir si cette DLL spécifique est dans le gac. Vous pouvez utiliser gacutil.exe avec l'option/l de la ligne de commande pour afficher le contenu du GAC.

+0

J'aimerais pouvoir - j'ai un accès limité au serveur - c'est-à-dire, FTP uniquement :) mais encore, merci pour le commentaire – effkay

+0

@effkay - désolé, ce n'était pas utile. Si vous avez un accès limité au serveur, comment une solution de code vous aidera-t-elle? –

+0

@MikeTwo On dirait qu'il prévoit de télécharger une page Web qui énumérera quels assemblages sont dans le GAC. – BrainSlugs83

-3

Peut être vous avez besoin spectateur GAC quelque chose comme ceci:

alt text

Video: How to use Add GAC References Dialog

Hope this helps

s

+0

Cela ne va pas aider car il a dit qu'il a seulement un accès FTP au serveur. Il veut être en mesure d'énumérer le GAC en utilisant le code C# qui est exécuté dans un environnement d'approbation moins que complet. – BrainSlugs83

3

Si c'est site laideron ASP.NET, et l'assembly ne se trouve pas dans le dossier bin du site ou dans le GAC du serveur (et il n'y a rien dans le fichier web.config), peut-être que le site est un sous-site de quelque sorte et l'un des plus hauts du site contient la référence dans le dossier bin (ou quelque chose de louche dans son web.config, puisque les sous-sites/dossiers héritent les web.configs de leurs parents) ? Maintenant, si vous avez un environnement où le fichier est chargé correctement (et cela vous semble), vous pouvez simplement demander à .NET où.dll vient et afficher qu'au lieu, par exemple:

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

Console.WriteLine(a.Location); 

chargera un assemblage et afficher son emplacement sur le disque, ma sortie est: C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.Shell\2.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Shell.dll

Si elle est sous « C: \ Windows \ assembly "vous savez que c'est dans le GAC.

Vous pouvez aussi le faire sans appel Assembly.Load si vous référence déjà l'assemblage, vous pouvez énumérer les ensembles chargés dans le courant app.domain et juste imprimer (ou rendre à un contrôle littéral ou Response.Write, etc ...) quelles sont leurs propriétés .Location.

Edit: Le code pour cela ressemble à quelque chose comme ceci:

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

Edit: sur un environnement de confiance totale, le code suivant (application de la console) énumérera le GAC et écrire chaque assembly, il devrait être facile de le modifier dans une application ASP.NET, mais je ne suis pas sûr si cela fonctionnera dans un environnement qui est moins de confiance totale (juste deviner ici, vous pourriez avoir de la chance):

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

une méthode simple pour énumérer les fichiers dll dans un répertoire

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

et vous pouvez obtenir tous les fichiers

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

Si vous devez charger chaque assemblage, vous obtenez une exception pour l'exécution différent version. Pour cette raison, vous pouvez charger l'assemblage avec Assembly.ReflectionOnlyLoadFrom pour charger l'assemblage en réflexion uniquement. Ensuite, Assembly ne charge pas dans votre AppDomain et ne lance pas d'exception.

1

me dis que je pourrais aussi bien jeter dans ma solution LINQ (pratique si votre à la recherche d'un seul fichier et ne veulent pas énumérer tous les fichiers)

fonction

pour trouver les fichiers:

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

Et d'appeler (je n'avais pas Environment.SpecialFolder.Windows donc utilisé à la place Environment.SpecialFolder.System)

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

de plus, en tant que FYI cette méthode enume évalue le GAC entier et vous pouvez trouver des DLL dupliquées dans tmp/et temp /, Tmp est utilisé pour l'installation et Temp est utilisé pour la désinstallation.

Questions connexes