public void CleanGAC() { IAssemblyName an; // get all GAC components IAssemblyEnum ae = AssemblyCache.CreateGACEnum(); // [...]
while (AssemblyCache.GetNextAssembly(ae, out an) == 0) { // get name string l_strName = AssemblyCache.GetName(an).ToUpper();
// [...]
try { // delete an assembly from the GAC new System.EnterpriseServices.Internal.Publish().GacRemove(l_strName); //[...] } catch (Exception ex) { throw new Exception(String.Format("CleanMain.CleanGAC: Error removing {0}. {1}", l_strName, ex.Message)); } } }
Bei jedem Löschversuch wird eine Variable hochgezählt, die mir dann am Schluss mitteilt, wieviele Dll's gelöscht worden sind. Es werden auch nicht irgendwelche Dll's gelöscht, sondern nur welche mit bestimmten Parametern.
Nur, funktioniert das Ganze nicht so wie es sollte. Es löscht keine Dll's. Ich habe mittlerweile herausgefunden, dass es wahrscheinlich daran liegt, dass die Funktion GacRemove nicht einfach einen Assembly-Namen braucht, sondern einen ganzen Pfad.
Wie bekomme ich nun den Pfad einer Dll aus dem GAC heraus, so dass ich sie löschen kann?
Es ist nicht möglich eine DLL direkt über das GAC-Verzeichnis zu löschen. Mit direkt mein ich dabei das du den Pfad aus dem GAC-Verzeichnis als Parameter für GacRemove verwendest.
Du musst die DLL aus dem GAC-Verzeichnis z.B. ins Temp-Verzeichnis kopieren und dann GacRemove mit dem Pfad der DLL aus dem Tempverzeichnis aufrufen.
Beispiel:
string original = "C:\WINDOWS\assembly\GAC_32\System.Data\2.0.0.0__b77a5c561934e089\System.Data.dll"; string target = "C:\temp\System.Data.dll"
//Kopie erstellen File.Copy(original , target);
//Aus dem GAC entfernen new System.EnterpriseServices.Internal.Publish().GacRemove(target);
//Kopie löschen File.Delete(target);
Nachtrag
Selbstverständlich geht auch jede andere Kopie der DLL der selben Version.
Nachtrag 2
How to search a File recursively from subfolder using LINQ.
Nachdem die Frage aufkam, warum nur Assamblys gelistet werden, bei denen Any-CPU als Prozessorarchitektur ausgewählt ist und keine mit x86 or MSIL: Das liegt daran das diese jeweils in eigenen Verzeichnissen im GAC verwaltet werden.
@"..\assembly\" //Basisverzeichnis mit diveresen Unterverzeichnissen wie temp, NativImage_..., etc.
Die Funktion findet ein paar Dll's (126 um genau zu sein, aber dafür mit vollständigen Pfaden), jedoch keine einzige, die ich jedoch haben will. In der Variablen files[] sind längst nicht alle Dll's drin (allein im GAC gibt 491 Einträge).
Noch ein paar Informationen vorweg: Ich arbeite hier mit .NET 2.0, da gab es die Version Environment.SpecialFolder.Windows nicht, deswegen habe ich die obige Variante genommen.
Das habe ich in meinem Test auch festgestellt. Die Frameworkeigenenen DLLs tauchen darin nicht auf. Die von mir registrieren DLLs jedoch schon. Warum die von dir registrieren nicht auftauchen kann ich mir aber auch nicht erklären.
Ich kanns glaub ich erklären. Ich hab mal die Einträge im GAC mit denen aus der Liste verglichen. Ich hab nicht alle durchsucht, sondern die ersten. Mir ist dabei aufgefallen, dass nur diejenigen DLL's angezeigt worden sind, bei denen im GAC in der Spalte Prozessorarchitektur nichts stand. Wenn aber dort steht MSIL oder x86 oder sonst was, dann wird die DLL nicht mit in die Liste aufgenommen.