2009-10-21 13 views
11

Come è possibile enumerare tutti gli assembly disponibili in GAC in C#?enumerazione di assembly in GAC

In realtà sto affrontando un problema con un codice stupido - l'assembly chiamato Telerik.Web.UI.dll viene indirizzato e utilizzato nel progetto - questa particolare DLL non è presente nella cartella BIN. E l'applicazione sta funzionando bene sul server - ma sulla mia macchina, ovviamente il compilatore sta dando un errore. Ex-Developer insiste sul fatto che non è in GAC sul server e "è quello che è". Ora ho bisogno di controllare se questa DLL è registrata in GAC o no.

L'aiuto sarà apprezzato.

Buon giorno;

+0

@effkey: sei riuscito a risolvere questo problema? – Kev

+0

nop; Non ero in grado di; piuttosto ho scaricato i file .dll di torrent (stessa versione) e hanno funzionato. Non riesco ancora a capire da dove ASP .NET preleva il DLLz se non si trova in GAC. – effkay

risposta

10

Se si dispone di un accesso limitato al server allora questo potrebbe funzionare:

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

enumera fondamentalmente le cartelle GAC prime. Funziona su hosting condiviso DiscountASP, quindi potrebbe funzionare per il tuo ambiente di hosting.

Potrebbe essere impreziosito enumerando più in profondità nella cartella di ciascun assieme per estrarre il numero di versione e il token della chiave pubblica.

4

Controllare questo articolo codeproject GAC API Interface. Questo utilizza fusion.dll non documentato per enumurare il GAC. Ma l'autore afferma che

Questo codice è noto per funzionare con .NET 1.1 e 2.0. Si noti che la DLL fusion.dll è diversa in 1.1 e 2.0. Quindi se hai entrambi i framework installati, assicurati di puntare il codice alla giusta DLL. In caso contrario, la maggior parte delle chiamate API avrà esito negativo. L'implementazione di default utilizza quella trovata in nella directory di WINDOWS.

+0

grazie - controllerà; ma temo che potrebbe creare un problema con le autorizzazioni; poiché ho un accesso limitato al server - e dubito della sua funzionalità in ASP NET User. ma grazie comunque; L'ho visto anche prima, ma ho escluso il dubbio sopra. Ma lasciatemi fare un tentativo. – effkay

+1

Non è non documentato. Almeno non più. https://support.microsoft.com/kb/317540 o http://msdn.microsoft.com/en-us/library/ms404523.aspx –

4

Non hai davvero bisogno di scrivere qualcosa in C# per scoprire se questa dll specifica è nel gac. È possibile utilizzare gacutil.exe con l'opzione/l dalla riga di comando per elencare il contenuto del GAC.

+0

desidero potrei avere accesso limitato al server, ad es., Solo FTP :) ma ancora, grazie per il commento – effkay

+0

@effkay - scusa non è stato utile. Se si dispone di un accesso limitato al server, in che modo una soluzione di codice può essere d'aiuto? –

+0

@MikeTwo Sembra che stia pianificando di caricare una pagina Web che elencherà gli assembly presenti nel GAC. – BrainSlugs83

-3

Può essere necessario GAC spettatore qualcosa di simile:

alt text

Video: How to use Add GAC References Dialog

Spero che questo aiuti

s

+0

Ciò non aiuterà poiché ha solo accesso FTP al server. Vuole essere in grado di enumerare il GAC usando il codice C# che viene eseguito in un ambiente di fiducia meno completo. – BrainSlugs83

3

Se è plain-jane sito ASP.NET, e l'assembly non si trova nella cartella bin del sito o nel GAC del server (e non c'è nulla di pericoloso nel web.config), forse il sito è un sito secondario di qualche tipo e uno dei siti più in alto contiene il riferimento nella cartella bin (o qualcosa di interessante nel suo web.config, dal momento che siti secondari/cartelle ereditano i web.configs dei loro genitori) ?

Ora, se si dispone di un ambiente in cui il file viene caricato correttamente (e suona come si fa), è sufficiente chiedere a .NET dove si trova.dll è in arrivo da e visualizzare che invece, per esempio:

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

Console.WriteLine(a.Location); 

caricherà un assieme e visualizzare la relativa posizione su disco, la mia uscita è: C:\Windows\assembly\GAC_MSIL\Microsoft.VisualStudio.Shell\2.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.Shell.dll

Se è sotto "C: \ Windows \ assembly \ "sai che è nel GAC.

È inoltre possibile eseguire questa operazione senza una chiamata Assembly.Load se si fa già riferimento all'assembly, è possibile enumerare gli assembly caricati nell'app.dominio corrente e stampare (o eseguire il rendering su un controllo letterale o su Response.Write, ecc ...) quali sono le loro proprietà .Location.

Edit: Il codice per che sembra qualcosa di simile:

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

Edit: In un ambiente di fiducia piena, il seguente codice (console app) sarà enumerare la GAC ​​e scrivere ogni assembly, dovrebbe essere facile modificarlo in un'app ASP.NET, ma non sono sicuro che funzionerà in un ambiente che non è completamente affidabile (basta indovinare qui, potresti essere fortunato):

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 metodo semplice per enumerare i file dll in una directory

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

e si può ottenere tutti i file

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

Se avete bisogno di caricare ogni gruppo, si ottiene un eccezione per i diversi run-time versione. Per questo motivo è possibile caricare l'assemblaggio con Assembly.ReflectionOnlyLoadFrom per caricare solo il gruppo di riflessione. Quindi, Assembly non viene caricato nel tuo AppDomain e non genera eccezioni.

1

figura potrei anche gettare nella mia soluzione a base di LINQ (utile se il vostro solo in cerca di un singolo file e non vogliono per enumerare tutti i file)

funzione per trovare i file:

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

E per chiamare (non ho avuto Environment.SpecialFolder.Windows così abituati Environment.SpecialFolder.System invece)

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

Inoltre, come un FYI questo metodo enume valuta l'intero GAC e potresti trovare dll duplicati in tmp/e temp /, Tmp è usato per l'installazione e Temp è usato per la disinstallazione.

Problemi correlati