2009-10-21 6 views
11

Wie kann ich alle verfügbaren Assemblys in GAC in C# aufzählen?Auflisten von Assemblys in GAC

Eigentlich habe ich ein Problem mit einem dummen Code - die Assembly namens Telerik.Web.UI.dll wird verwiesen und im Projekt verwendet - diese bestimmte DLL ist nicht in BIN-Ordner vorhanden. Und die Anwendung funktioniert gut auf dem Server - aber auf meinem Rechner gibt der Compiler offensichtlich Fehler. Ex-Entwickler besteht darauf, dass es nicht in GAC auf dem Server ist und "es ist was es ist". Jetzt muss ich überprüfen, ob diese DLL in GAC registriert ist oder nicht.

Hilfe wird geschätzt.

Guten Tag;

+0

@effkey - haben Sie es geschafft, dieses Problem zu lösen? – Kev

+0

nop; Ich war nicht in der Lage zu; Stattdessen habe ich die .dll-Dateien von Torrents heruntergeladen (gleiche Version) und sie haben funktioniert. Ich verstehe immer noch nicht von wo ASP.NET die DLLz abholt, wenn sie nicht in GAC sind. – effkay

Antwort

10

Wenn Sie beschränkten Zugriff auf den Server haben, dann könnte dies funktionieren:

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

Es zählt im Grunde die rohen GAC Ordner. Es funktioniert auf dem Shared Hosting von DiscountASP und könnte daher für Ihre Hosting-Umgebung funktionieren.

Es könnte verschönert werden, indem man tiefer in den Ordner jeder Assembly aufzählt, um die Versionsnummer und das Token des öffentlichen Schlüssels herauszuziehen.

4

Überprüfen Sie diese codeproject GAC API Interface Artikel. Dies verwendet undokumentierte fusion.dll, um den GAC zu erweitern. Aber der Autor behauptet, dass

Dieser Code ist bekannt, mit .NET 1.1 und 2.0 zu arbeiten. Bitte beachten Sie, dass sich die DLL fusion.dll in 1.1 und 2.0 unterscheidet. Wenn Sie also beide Frameworks installiert haben, stellen Sie sicher, dass Sie den Code auf die richtige DLL verweisen. Ansonsten werden die meisten API-Aufrufe fehlschlagen. Die Standardimplementierung verwendet die im Verzeichnis WINDOWS in gefundene.

+0

danke - wird überprüft; aber ich fürchte, es könnte ein Problem mit Berechtigungen verursachen; da ich eingeschränkten Zugriff auf den Server habe - und ich bezweifle seine Funktionalität unter ASP NET User. aber danke trotzdem; Ich habe es auch früher gesehen, aber ausgeschlossen über jeden Zweifel. Aber lemme es versuchen. – effkay

+1

Es ist nicht undokumentiert. Zumindest nicht mehr. https://support.microsoft.com/kb/317540 oder http://msdn.microsoft.com/en-us/library/ms404523.aspx –

4

Sie müssen nicht wirklich etwas in C# schreiben, um herauszufinden, ob diese spezifische DLL im gac ist. Sie können gacutil.exe mit der Option/l von der Befehlszeile aus verwenden, um den Inhalt des GAC aufzulisten.

+0

Ich wünschte, ich könnte - ich habe begrenzten Zugriff auf Server - d., Nur FTP :) aber immer noch, danke für den Kommentar – effkay

+0

@effkay - Entschuldigung, es war nicht hilfreich. Wenn Sie nur eingeschränkten Zugriff auf den Server haben, wie hilft eine Codelösung? –

+0

@MikeTwo Klingt, als ob er plant, eine Webseite hochzuladen, die auflisten wird, welche Assemblys im GAC sind. – BrainSlugs83

-3

Mai werden Sie GAC Betrachter so etwas wie dieses benötigen:

alt text

Video: How to use Add GAC References Dialog

this helps

s

+0

Das wird nicht helfen, wie er sagte, er hat nur FTP-Zugriff auf den Server. Er möchte in der Lage sein, den GAC mit C# -Code aufzuzählen, der in einer Umgebung ausgeführt wird, in der weniger als die volle Vertrauenswürdigkeit gilt. – BrainSlugs83

3

Wenn es plain-jane ASP.NET-Website, und die Assembly befindet sich nicht im bin-Ordner der Site oder im GAC des Servers (und in der Datei web.config ist nichts faul), Vielleicht ist die Site eine Unter-Site irgendeiner Art und eine der höher gelegenen Sites enthält die Referenz im bin-Ordner (oder etwas Fischiges in ihrer web.config, da Sub-Sites/Ordner die Web-Configs ihrer Eltern erben) ?

Nun, wenn Sie eine Umgebung haben, in der die Datei korrekt geladen wird (und es klingt wie Sie), können Sie einfach fragen, wo.dll herkommt und zeigt, dass statt, zum Beispiel:

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

Console.WriteLine(a.Location); 

Wird eine Baugruppe geladen und angezeigt seine platte Lage, meine Ausgabe ist: C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.Shell\2.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Shell.dll

Wenn es unter „C: \ Windows \ Assembly \ "Sie wissen, dass es in der GAC ist.

Sie können dies auch ohne Assembly.Load tun, wenn Sie bereits auf die Assembly verweisen, können Sie die in der aktuellen app.domain geladenen Assemblies auflisten und einfach ausdrucken (oder in ein Literal-Steuerelement rendern oder Response.Write, etc ...) was ihre .Location Eigenschaften sind.

Edit: Der Code für das sieht etwa so aus:

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

Edit: Auf einer voll vertrauenswürdigen Umgebung, der folgende Code (Konsolenanwendung) wird die GAC aufzählen und schreiben Bei jeder Assembly sollte es leicht sein, sie in eine ASP.NET-App zu ändern, aber ich bin mir nicht sicher, ob sie in einer Umgebung funktioniert, die weniger als voll vertrauenswürdig ist (nur hier können Sie Glück haben):

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

eine einfache Methode, DLL-Dateien in einem Verzeichnis

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

aufzuzählen und Sie können alle Dateien

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

Wenn Sie jede Baugruppe laden müssen erhalten, erhalten Sie eine Ausnahme für verschiedene Laufzeit Ausführung. Aus diesem Grund können Sie die Baugruppe mit Assembly.ReflectionOnlyLoadFrom laden, um die Baugruppe nur in Reflexion zu laden. Dann lädt Assembly nicht in Ihrer Anwendungsdomäne und löst keine Ausnahme aus.

1

Abbildung könnte ich auch in meine Linq-basierte Lösung werfen (praktisch, wenn Ihr nur für eine einzelne Datei suchen und wollen nicht durch jede Datei aufzuzählen)

Funktion, die Dateien zu finden:

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

Und nennen

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

Weiterhin als FYI diese Methode enume (i nicht Environment.SpecialFolder.Windows so gebrauchte Environment.SpecialFolder.System stattdessen hatte) bewertet den gesamten GAC und Sie finden möglicherweise doppelte DLLs in tmp/und temp /, Tmp wird für die Installation verwendet und Temp wird für die Deinstallation verwendet.