12 Stimmen

Delphi, Ordner mit Inhalt löschen

Wenn ich Unterordner im Ordner habe - dieser Code löscht keine Ordner... Gibt es einen Fehler?

procedure TForm.Remove(Dir: String);
var
  Result: TSearchRec; Found: Boolean;
begin
  Found := False;
  if FindFirst(Dir + '\*', faAnyFile, Result) = 0 then
    while not Found do begin
      if (Result.Attr and faDirectory = faDirectory) AND (Result.Name <> '.') AND (Result.Name <> '..') then Remove(Dir + '\' + Result.Name)
      else if (Result.Attr and faAnyFile <> faDirectory) then DeleteFile(Dir + '\' + Result.Name);
      Found := FindNext(Result) <> 0;
    end;
  FindClose(Result); RemoveDir(Dir);
end;

35voto

David Heffernan Punkte 585606

Am einfachsten ist es, wenn Sie TDirectory.Delete(Dir, True) .

TDirectory findet sich in IOUtils was eine recht neue RTL-Ergänzung ist.

El True Flagge wird an die Recursive was bedeutet, dass der Inhalt der Verzeichnisse geleert wird, bevor das Verzeichnis entfernt wird, ein wesentlicher Bestandteil des Löschens von Verzeichnissen.


In einem Kommentar teilen Sie uns mit, dass Sie Delphi 7 verwenden und dies daher nicht verwendet werden kann.

Ihr Code sieht größtenteils gut aus. Allerdings meinen Sie nicht:

(Result.Attr and faAnyFile <> faDirectory)

Ich glaube, Sie meinen:

(Result.Attr and faDirectory <> faDirectory)

Ich würde es wahrscheinlich wie folgt schreiben:

procedure TMyForm.Remove(const Dir: string);
var
  Result: TSearchRec;
begin
  if FindFirst(Dir + '\*', faAnyFile, Result) = 0 then
  begin
    Try
      repeat
        if (Result.Attr and faDirectory) = faDirectory then
        begin
          if (Result.Name <> '.') and (Result.Name <> '..') then
            Remove(Dir + '\' + Result.Name)
        end
        else if not DeleteFile(Dir + '\' + Result.Name) then
          RaiseLastOSError;
      until FindNext(Result) <> 0;
    Finally
      FindClose(Result);
    End;
  end;
  if not RemoveDir(Dir) then
    RaiseLastOSError;
end;

30voto

Andreas Rejbrand Punkte 100651

An Ihrer Stelle würde ich das Betriebssystem einfach anweisen, den Ordner mit seinem gesamten Inhalt zu löschen. Schreiben Sie dazu ( uses ShellAPI )

var
  ShOp: TSHFileOpStruct;
begin
  ShOp.Wnd := Self.Handle;
  ShOp.wFunc := FO_DELETE;
  ShOp.pFrom := PChar('C:\Users\Andreas Rejbrand\Desktop\Test\'#0);
  ShOp.pTo := nil;
  ShOp.fFlags := FOF_NO_UI;
  SHFileOperation(ShOp);

[Wenn Sie das tun

  ShOp.fFlags := 0;

erhalten Sie stattdessen einen netten Bestätigungsdialog. Wenn Sie

ShOp.fFlags := FOF_NOCONFIRMATION;

erhalten Sie keinen Bestätigungsdialog, aber Sie erhalten einen Fortschrittsbalken, wenn der Vorgang länger dauert. Schließlich, wenn Sie die FOF_ALLOWUNDO verschieben Sie das Verzeichnis in den Papierkorb, anstatt es endgültig zu löschen.

ShOp.fFlags := FOF_ALLOWUNDO;

Natürlich können Sie die Flaggen nach Belieben kombinieren:

ShOp.fFlags := FOF_NOCONFIRMATION or FOF_ALLOWUNDO;

wird keine Bestätigung angezeigt (sondern ein Fortschrittsdialog, da Sie nicht angeben FOF_NO_UI ) und das Verzeichnis wird in den Papierkorb verschoben und nicht endgültig gelöscht].

10voto

Heinrich Ulbricht Punkte 9413

Das letzte Mal, als ich einen Ordner mit Inhalt löschen musste, habe ich die JCL :

uses JclFileUtils;

DeleteDirectory(DirToDelete, True);

Der letzte Parameter gibt an, ob die Dateien in den Papierkorb wandern sollen oder nicht, was ein netter Bonus ist.

6voto

Remy Lebeau Punkte 498719

Um das ursprüngliche Problem zu lösen - versuchen Sie Folgendes:

procedure TForm.Remove(const Dir: String);
var
  sDir: String;
  Rec: TSearchRec;
begin
  sDir := IncludeTrailingPathDelimiter(Dir);
  if FindFirst(sDir + '*.*', faAnyFile, Rec) = 0 then
  try
    repeat
      if (Rec.Attr and faDirectory) = faDirectory then
      begin
        if (Rec.Name <> '.') and (Rec.Name <> '..') then
          Remove(sDir + Rec.Name);
      end else
      begin
        DeleteFile(sDir + Rec.Name);
      end;
    until FindNext(Rec) <> 0;
  finally
    FindClose(Rec);
  end;
  RemoveDir(sDir);
end;

4voto

gabr Punkte 26255
uses DSiWin32;

DSiDeleteTree(folderName, false);

DSiWin32 ist ein Open-Source-Projekt, das unter einer "Use as you wish"-Lizenz veröffentlicht wird.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X