| Autor |
Beitrag |
LokutusvB
      
Beiträge: 74
WinXP
Delphi 5, Delphi XE
|
Verfasst: Mi 17.10.07 10:54
Hallo Leute,
ich habe ein Problem mit FindFirst. Ich möchte in einer Ordnerstruktur alle Unterordner und Dateien löschen. Nur geht das Programm bis in die tiefste Ordnerstruktur, löscht die Dateien und das war es. Etwas anderes kommt für mich leider nicht in Frage, da teilweise schreibgeschütze Dateien vorhanden sind, und die ShellAPI dort abbricht.
Findet jemand den Fehler? Ich komme momentan nicht mehr weiter.
Delphi-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| function TForm_Cleaner.leereOrdner(sStart: String): Boolean; var srAkt: TSearchRec; sPfad: String;
begin Result := True; sPfad := sStart + '\'; if (FindFirst(sPfad + '*.*', faAnyFile, srAkt) = 0) then begin REPEAT if (((srAkt.Attr and faDirectory) = faDirectory)) then if ((srAkt.Name <> '.') and (srAkt.Name <> '..')) then leereOrdner(sPfad + srAkt.Name); UNTIL FindNext(srAkt) <> 0; end; if (FindFirst(sPfad + '*.*', faAnyFile, srAkt) = 0) then begin REPEAT if (((srAkt.Attr and faDirectory) = faDirectory) and (DirectoryIsEmpty(sPfad + srAkt.Name)) and (srAkt.Name <> '.') and (srAkt.Name <> '..')) then try ShowMessage (sPfad + srAkt.Name); RemoveDir(sPfad + srAkt.Name); except Result := False; end; if (((srAkt.Attr and faDirectory) <> faDirectory) and (srAkt.Name <> '.') and (srAkt.Name <> '..') and (srAkt.Attr <> faReadOnly)) then try DeleteFile(sPfad + srAkt.Name); except Result := False; end; UNTIL FindNext(srAkt) <> 0; end; end; |
MFG
LokutusvB
|
|
Logikmensch
      
Beiträge: 390
Win XP
Delphi 2007 Prof., XE2, XE5
|
Verfasst: Mi 17.10.07 11:58
Hallo, ich habe Deine Funktion mal ein bisschen umgebaut. Im Wesentlichen sollte sie dasselbe tun, was Du möchtest. Wichtig ist auch das FindClose am Ende.
Die Routine ist momentan noch so geschrieben, dass sie auch komplett abbricht, falls irgendeine Datei nicht gelöscht werden kann.
Im Zweifelsfalle solltest Du vor dem Löschen einer Datei auch die Dateiattribute System und Versteckt zurücksetzen. Dann sollten sich Dateien, die sonst von niemandem geöffnet sind, gelöscht werden können.
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| function TForm_Cleaner.leereOrdner(sStart: String): Boolean; var srAkt: TSearchRec; sPfad: String; ok:boolean; begin Result := True; sPfad := includetrailingpathdelimiter(sStart); ok:=FindFirst(sPfad + '*.*', faAnyFile, srAkt)=0; count:=0; while ok and result do begin if (srAkt.Name <> '.') and (srAkt.Name <> '..') then begin if srAkt.Attr and faDirectory=faDirectory then begin if not leereOrdner(sPfad+srAkt.Name) then result:=false; end else begin try DeleteFile(sPfad+srAkt.Name); if FileExists(sPfad+srAkt.Name) then result:=false; except result:=false; end; end; end; ok:=FindNext(srAkt)=0; end; if result then begin try RemoveDir(sStart); if not DirectoryIsEmpty(sStart) then result:=false; except result:=false; end; end; FindClose(srAkt); end; |
_________________ Es gibt keine Probleme - nur Lösungen!
|
|
LokutusvB 
      
Beiträge: 74
WinXP
Delphi 5, Delphi XE
|
Verfasst: Mi 17.10.07 12:51
Titel: Interner Speicherfehler
Leider funktoniert das genauso gut bzw. genau so schlecht wie mein Ansatz.
Zum Test habe ich mir extra eine Ordnerstruktur frei von versteckten oder geschützen Ordnern und Dateien angelegt. Die Dateien löscht es, aber die Ordner bleiben erhalten, maxmimal wird der tiefste Ordner gelöscht, in dem es vorher Dateien gab.
Lösche ich dir Ordner einzeln mit Pfadangabe (RemoveDir), werden sie gelöscht.
Ich gehe hier jetzt auf Nummer sicher und speicher jeden Ordner in eine Stringlist und klappere dann die Liste ab, vielleicht geht das ja besser.
Zuatz:
Das liegt nicht an der Routine, sondern am Prozess selbst. Egel welche Routine, sobald ein Verzeichis mit FindFirst/Next in Berührung gebracht wurde, selbst wenn danach FindClose aufruft, erscheint bir RmDire ein E/A-Fehler.
Hat jemand schon mal das gleiche beobachtet und weiss Abhilfe?
Zusatz 2:
Das Problem liegt daran, dass der Prozess selbst das Verzeichnis noch nicht wieder freigeben hat, also Delphi schon, aber Windows noch nicht. Nachdem ich Sleep von 1000 zwischen dem FindFirst....FindClose und der nächsten Prozedur, welche alle Verzeichnisse der Reihe nach entnehmend aus der StringListe löscht, geht es nun wunderbar.
|
|
Logikmensch
      
Beiträge: 390
Win XP
Delphi 2007 Prof., XE2, XE5
|
Verfasst: Do 18.10.07 05:24
Uff. Sachen gibt's. Das wusste ich echt nicht. Aber ich hätte es mir auch denken können, dass es am Windows liegt, zumal ich auch mit dem Explorer oft auch das Problem habe, dass ich einen Ordner nicht löschen kann, selbst wenn er leer ist.
Wieder was dazugelernt. Hauptsache, es funzt.
Kannst den Code ja nochmal hier posten, dann haben wir alle was davon (ist auch für mich nicht uninteressant).
_________________ Es gibt keine Probleme - nur Lösungen!
|
|
LokutusvB 
      
Beiträge: 74
WinXP
Delphi 5, Delphi XE
|
Verfasst: Do 18.10.07 07:24
Ist noch nicht ganz fertig, die Auswertung der Rückgabeparameter fehlt noch. Aber vielleicht findest du ja auch noch so Verbesserungsmöglichkeiten
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72:
| function TForm_Cleaner.leereOrdner(sStart: String): Boolean; begin Result := True; slDir := TStringList.Create; findeOrdner(sStart); loescheOrdnerInhalt(sStart); sleep(500); loescheOrdner; FreeAndNil(slDir); end;
procedure TForm_Cleaner.findeOrdner(sStart: String); var srAkt: TSearchRec; sPfad: String;
begin sPfad := IncludeTrailingBackslash(sStart); if (FindFirst(sPfad + '*.*', faAnyFile, srAkt) = 0) then begin REPEAT if (((srAkt.Attr and faDirectory) = faDirectory)) then if ((srAkt.Name <> '.') and (srAkt.Name <> '..')) then begin slDir.Add(sPfad + srAkt.Name); findeOrdner(sPfad + srAkt.Name); end; UNTIL FindNext(srAkt) <> 0; end; FindClose(srAkt); end;
function TForm_Cleaner.loescheOrdnerInhalt(sStart: String): Boolean; var srAkt: TSearchRec; sTemp: String; ii: Integer;
begin Result := True; for ii := slDir.Count - 1 downto 0 do begin sTemp := IncludeTrailingBackslash(slDir.Strings[ii]); if (FindFirst(sTemp + '*.*', faAnyFile, srAkt) = 0) then begin REPEAT if (((srAkt.Attr and faDirectory) <> faDirectory) and (srAkt.Name <> '.') and (srAkt.Name <> '..') and (srAkt.Attr <> faReadOnly)) then try DeleteFile(sTemp + srAkt.Name); except Result := False; end; UNTIL FindNext(srAkt) <> 0; end; FindClose(srAkt); end; sTemp := IncludeTrailingBackslash(sStart); if (FindFirst(sTemp + '*.*', faAnyFile, srAkt) = 0) then begin REPEAT if (((srAkt.Attr and faDirectory) <> faDirectory) and (srAkt.Name <> '.') and (srAkt.Name <> '..') and (srAkt.Attr <> faReadOnly)) then try DeleteFile(sTemp + srAkt.Name); except Result := False; end; UNTIL FindNext(srAkt) <> 0; end; FindClose(srAkt); end;
Function TForm_Cleaner.loescheOrdner: Boolean; var sTemp: String; ii: Integer;
begin Result := True; for ii := slDir.Count -1 downto 0 do begin sTemp := slDir.Strings[ii]; if (DirectoryIsEmpty(sTemp)) then begin try RmDir(sTemp); except Result := False; end; end; end; end; |
|
|
|