AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Datei aus dem Papierkorb wiederherstellen
Thema durchsuchen
Ansicht
Themen-Optionen

Datei aus dem Papierkorb wiederherstellen

Ein Thema von Benmik · begonnen am 27. Aug 2014 · letzter Beitrag vom 28. Aug 2014
Antwort Antwort
Benmik

Registriert seit: 11. Apr 2009
570 Beiträge
 
Delphi 12 Athens
 
#1

AW: Datei aus dem Papierkorb wiederherstellen

  Alt 27. Aug 2014, 20:28
1. Hinter For..end ist die Schleifenvariable definitionsgemäß undefiniert.
2. Bei einer While-Konstruktion ist i immer definiert, da es sich um eine initialisierte Variable handelt. Hier dürfte man übrigens auch eine globale Variable verwenden, was bei For nicht erlaubt ist.
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
570 Beiträge
 
Delphi 12 Athens
 
#2

AW: Datei aus dem Papierkorb wiederherstellen

  Alt 27. Aug 2014, 20:45
So, jetzt hat es mich natürlich doch gejuckt und ich habe das Ganze OOP-mäßig in Klassen verpackt.
Wie erwähnt, hat mich die Erweiterbarkeit gereizt.
Das Ganze hat jetzt 5 Funktionalitäten:
  1. Anzahl der Dateien im Papierkorb ermitteln
  2. Liste aller Dateien im Papierkorb erstellen (mit Filterfunktion!)
  3. Datei in den Papierkorb verschieben
  4. Datei aus dem Papierkorb wiederherstellen
  5. Papierkorb leeren

Delphi-Quellcode:
unit Papierkorb;

interface

uses Windows,Contnrs,Forms,Classes,SysUtils,ShellAPI,Masks,COMObj,shlobj,ActiveX;

type
  TPIDLItem = class
  private
    FDateiname: String;
    FIDL : PItemIDList;
  protected
  public
end;

type
  TPapierkorb = class
  private
    FPIDLListe: TObjectList;
    FDeskDirI : IShellFolder;
    FRecycleI : IShellFolder;
    FpReIDL : PItemIDList;
    FpNextIDL : PItemIDList;
    FpItemIDL : PItemIDList;
    FEnumList : IENUMIDLIST;
    FCmInfo : CMINVOKECOMMANDINFO;
    FContextI : IContextMenu;
    FIsThere : Cardinal;
    FStrRet : TStrRet;
    FparName : String;
    FPIDLItem : TPIDLItem;
    procedure SetzePapierkorbInterface;
    procedure NeueDatei(var PPIDLItem:TPIDLItem);
    function ListePapierkorbDateienAuf(Maske:string = ''):Boolean;
    function PKDateiWiederhergestellt(ListNr:integer;Dateiname:string):Boolean;
    function DateiInPKGefunden(Dateiname:string;var ListNr:integer):Boolean;
    function VerschiebeDateiInPK(var Dateiname: string;PlusNull:Boolean):Boolean;
  protected
  public
    constructor Create();
    destructor Destroy(); override;
    function ErstellePKDateiListe(const DateiListe:TStringList;Maske:string = ''):Boolean;
    function StellePKDateiWiederHer(Dateiname:string):Boolean;
    function ErmittleAnzPKDateien(Maske:string = ''):integer;
    function LeerePapierkorb:Boolean;
    function DateiInPapierkorb(Dateiname: string): Boolean;
end;
function SHEmptyRecycleBin(Wnd:HWnd; LPCTSTR:PChar; DWORD:Word):Integer; stdcall;
function SHEmptyRecycleBin; external 'SHELL32.DLLname 'SHEmptyRecycleBinA';

implementation

constructor TPapierkorb.Create;
begin
  inherited Create;
  FPIDLListe := TObjectList.Create;
end;

destructor TPapierkorb.Destroy;
begin
  FPIDLListe.Free;
  FPIDLListe := nil;
  inherited;
end;

function TPapierkorb.ErstellePKDateiListe(const DateiListe:TStringList;Maske:string = ''):Boolean;
var i:integer;
begin
  SetzePapierkorbInterface;
  Result := ListePapierkorbDateienAuf(Maske);
  If Result then begin
    For i := 0 to FPIDLListe.Count - 1 do
      DateiListe.Add(TPIDLItem(FPIDLListe[i]).FDateiname);
  end;
end;

function TPapierkorb.StellePKDateiWiederHer(Dateiname:string):Boolean;
var ListNr:integer;
begin
  SetzePapierkorbInterface;
  ListePapierkorbDateienAuf;
  Result := DateiInPKGefunden(Dateiname,ListNr) and PKDateiWiederhergestellt(ListNr,Dateiname);
end;

function TPapierkorb.ErmittleAnzPKDateien(Maske:string = ''):integer;
begin
  SetzePapierkorbInterface;
  If ListePapierkorbDateienAuf(Maske)
    then Result := FPIDLListe.Count
    else Result := -1;
end;

function TPapierkorb.DateiInPKGefunden(Dateiname:string;var ListNr:integer):Boolean;
var i:integer;
begin
  ListNr := -1;
  Try
    For i := 0 to FPIDLListe.Count - 1 do begin
      If SameFileName(TPIDLItem(FPIDLListe[i]).FDateiname,Dateiname) then begin
        ListNr := i;
        break;
      end;
    end;
  Finally
    Result := (ListNr > -1);
  End;
end;

function TPapierkorb.PKDateiWiederhergestellt(ListNr:integer;Dateiname:string):Boolean;
begin
  Try
    FpItemIDL := TPIDLItem(FPIDLListe[ListNr]).FIDL;
    If FpItemIDL <> nil then begin
      ZeroMemory(@FCmInfo, SizeOf(FCmInfo));
      FCmInfo.cbSize:= SizeOf(FCmInfo);
      FCmInfo.fMask:= CMIC_MASK_FLAG_NO_UI;
      FCmInfo.hwnd:= Application.Handle;
      FCmInfo.lpVerb:= 'undelete';
      FCmInfo.nShow:= SW_SHOWDEFAULT;
      OleCheck(FRecycleI.GetUIObjectOf(Application.Handle, 1, FpItemIDL, IID_IContextMenu, nil, FContextI));
      OleCheck(FContextI.InvokeCommand(FCmInfo));
    end;
  Except
    CoTaskMemFree(FpItemIDL);
  end;
  // Result := True;
  Result := FileExists(Dateiname);
end;

function TPapierkorb.ListePapierkorbDateienAuf(Maske:string = ''):Boolean;
begin
  Result := True;
  Try
    OleCheck(FRecycleI.EnumObjects(Application.Handle, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS or SHCONTF_INCLUDEHIDDEN, FEnumList));
    While FEnumList.Next(1, FpNextIDL, FIsThere) = S_OK do begin
      If FIsThere > 0 then begin
        OleCheck(FRecycleI.GetDisplayNameOf(FpNextIDL, SHGDN_NORMAL, FStrRet));
        case FStrRet.uType of
          STRRET_CSTR: FparName := FStrRet.cStr;
          STRRET_OFFSET: FparName := PChar(Cardinal(FpNextIDL) + FStrRet.uOffset);
          STRRET_WSTR: FparName := FStrRet.pOleStr;
        end;
      end;
      If FpNextIDL <> nil then begin
        If (Maske = '') or MatchesMask(FparName,Maske) then begin
          FPIDLItem := TPIDLItem.Create;
          FPIDLItem.FDateiname := FparName;
          FPIDLItem.FIDL := FpNextIDL;
          NeueDatei(FPIDLItem);
        end;
      end;
    end;
  except
    Result := False;
  end;
  CoTaskMemFree(FpNextIDL);
end;

procedure TPapierkorb.NeueDatei(var PPIDLItem:TPIDLItem);
begin
  FPIDLListe.Add(PPIDLItem);
end;

function TPapierkorb.LeerePapierkorb:Boolean;
const
  SHERB_NOCONFIRMATION = $00000001;
  SHERB_NOPROGRESSUI = $00000002;
  SHERB_NOSOUND = $00000004;
begin
  Result := (SHEmptyRecycleBin(0, nil, SHERB_NOCONFIRMATION or SHERB_NOPROGRESSUI or SHERB_NOSOUND) = 0);
end;

function TPapierkorb.DateiInPapierkorb(Dateiname: string): Boolean;
begin
  Result := FileExists(Dateiname);
  If Result then begin
    // Erst kein, dann ein, und dann zwei Nullzeichen hinter den Dateinamen setzen -> drei Mal ist Bremer Recht!
    Result := VerschiebeDateiInPK(Dateiname,False);
    If not Result then begin
      Result := VerschiebeDateiInPK(Dateiname,True);
      If not Result
        then Result := VerschiebeDateiInPK(Dateiname,True);
    end;
  end;
end;

function TPapierkorb.VerschiebeDateiInPK(var Dateiname: string;PlusNull:Boolean):Boolean;
var DatStrukt: TSHFileOpStruct; Ergebnis:integer;
begin
  // Es müssen ZWEI Nullzeichen am Dateiende sein, das klappt nicht immer
  If PlusNull
    then Dateiname := Dateiname + #0;
  FillChar(DatStrukt, SizeOf(DatStrukt), 0);
  DatStrukt.wFunc := FO_DELETE;
  DatStrukt.pFrom := PChar(Dateiname);
  DatStrukt.fFlags := FOF_ALLOWUNDO or FOF_NOCONFIRMATION or FOF_SILENT;
  Ergebnis := ShFileOperation(DatStrukt);
  Result := (Ergebnis = 0);
end;

procedure TPapierkorb.SetzePapierkorbInterface;
begin
  OleCheck(SHGetDesktopFolder(FDeskDirI));
  OleCheck(SHGetSpecialFolderLocation(Application.Handle, CSIDL_BITBUCKET, FpReIDL));
  OleCheck(FDeskDirI.BindToObject(FpReIDL, nil, IShellFolder, FRecycleI));
  CoTaskMemFree(FpReIDL);
end;

end.
Ausprobieren kann man das mit einem neuen Projekt, dazu eine Listbox, drei Buttons und ein Edit auf die Form bringen, TPapierkorb einbinden und dann:
Delphi-Quellcode:
uses Papierkorb;

procedure TForm1.Button1Click(Sender: TObject);
var PK:TPapierkorb; Liste:TStringList;
begin
  ListBox1.Clear;
  Liste := TStringList.Create;
  Liste.Sorted := True;
  Form1.Position := poDesktopCenter;
  PK := TPapierkorb.Create;
  PK.ErstellePKDateiListe(Liste,Edit1.Text);
  ListBox1.Items.Assign(Liste);
  PK.LeerePapierkorb;
  PK.Free;
end;

procedure TForm1.Button2Click(Sender: TObject);
var PK:TPapierkorb;
begin
  ListBox1.Clear;
  Form1.Position := poDesktopCenter;
  PK := TPapierkorb.Create;
  ListBox1.Items.Add('Es sind ' + IntToStr(PK.ErmittleAnzPKDateien(Edit1.Text)) + ' Dateien gemäß Ihren Kriterien im Papierkorb vorhanden.');
  PK.Free;
end;

procedure TForm1.Button3Click(Sender: TObject);
var PK:TPapierkorb;
begin
  If ListBox1.ItemIndex = -1 then begin
    ShowMessage('Scherzkeks! Kein Eintrag ausgewählt! ');
  end else begin
    PK := TPapierkorb.Create;
    If PK.StellePKDateiWiederHer(ListBox1.Items[ListBox1.ItemIndex])
      then Showmessage('Die Datei' + Chr(13) + Chr(13) + ListBox1.Items[ListBox1.ItemIndex] + Chr(13) + Chr(13) + 'wurde wiederhergestellt. ')
      else Showmessage('Die Datei' + Chr(13) + Chr(13) + ListBox1.Items[ListBox1.ItemIndex] + Chr(13) + Chr(13) + 'konnte nicht wiederhergestellt werden. ');
    PK.Free;
  end;
end;
Eine Sache ist mir unklar: Muss der Anwender Free aufrufen?

Geändert von Benmik (28. Aug 2014 um 00:39 Uhr) Grund: Anregungen eingearbeitet
  Mit Zitat antworten Zitat
hoika

Registriert seit: 5. Jul 2006
Ort: Magdeburg
8.276 Beiträge
 
Delphi 10.4 Sydney
 
#3

AW: Datei aus dem Papierkorb wiederherstellen

  Alt 27. Aug 2014, 22:04
Hallo,

ja, solange nicht mit Interfaces gearbeitet wird.

Die Sache mit dem i hinter der For-Schleife ist leicht erklärt.
Deine Code-Formatierung sah so aus, als ob du auf die Schleifenvariable nach der For-Schleife zugreifst,
hast du aber nicht.

Delphi-Quellcode:
PapierkorbDateienAuflisten;
For i := 0 to PIDLListe.Count - 1 do
begin
  If SameText(PPIDLItem(PIDLListe[i])^.Dateiname,Dateiname) then
  begin
    pItemIDL := PItemIDList(PPIDLItem(PIDLListe[i])^.IDL);
    break;
  end;
  If i = PIDLListe.Count - 1 then
  begin
    // das ist eh falsch, denn i ist = PIDLListe.Count, wenn nichts gefunden wurde
    // LeerePIDLListe;
    exit;
  end;
Heiko
Heiko

Geändert von hoika (27. Aug 2014 um 22:07 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.326 Beiträge
 
Delphi 12 Athens
 
#4

AW: Datei aus dem Papierkorb wiederherstellen

  Alt 27. Aug 2014, 22:23
Wir wäre es, wenn man einfach das prüft, was man prüfen wollte?
"Wurde nichts gefunden?" statt "Bin ich am Ende der Liste?"

Delphi-Quellcode:
pItemIDL := nil;
For i := 0 to PIDLListe.Count - 1 do
  If SameFileName(PPIDLItem(PIDLListe[i])^.Dateiname, Dateiname) then begin
    pItemIDL := PItemIDList(PPIDLItem(PIDLListe[i])^.IDL);
    break;
  end;
If not Assigned(pItemIDL) then begin
  // LeerePIDLListe;
end;
Delphi-Referenz durchsuchenSameFileName


Und die Fehlerbehandlung im ersten Post ist echt grausam.
  • Resourcenschutzblöcke fehlen komplett
    Delphi-Quellcode:
    OleCheck(SHGetSpecialFolderLocation(Application.Handle, CSIDL_BITBUCKET, pReIDL));
    OleCheck(DeskDirI.BindToObject(pReIDL, nil, IShellFolder, RecycleI));
    CoTaskMemFree(pReIDL);
    Wer gibt pReIDL frei, wenn es in BindToObject knallt?
  • Und die Try-Except sind das Schlimmste, was ich je gesehn hab.
    Exceptions werden zwar abgefangen, aber dann ohne Behandlung und vorallem ohne Auswertung/Anzeige der Fehlerursache einfach weggeworfen.
    Da wäre es besser gewesen, wenn man einfach ganz darauf verzichtet hätte.
  • OK, wenigstens wurden via OleCheck die Rückgabewerte geprüft, was schonmal ein Anfang ist,
    aber da dann der ausgelöste Fehler praktisch iignoriert wird, ist es praktisch nutzlos, aber wenigstens sorgt es dafür, daß der Nachfolgende Code (bis zum nächsten Except) nicht fehlerhaft ausgeführt wird.
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (27. Aug 2014 um 22:35 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
1.683 Beiträge
 
Delphi 5 Professional
 
#5

AW: Datei aus dem Papierkorb wiederherstellen

  Alt 27. Aug 2014, 23:14
Warum ist DateiListe der Methode TPapierkorb.ErstellePKDateiListe ein var -Parameter? Stattdessen gehört da ein const hin, weil der Zeiger auf die Liste konstant zu bleiben hat; Strings hinzufügen kann man trotzdem. Ich weiß, meckern ist immer einfach .

MfG Dalai
  Mit Zitat antworten Zitat
Benmik

Registriert seit: 11. Apr 2009
570 Beiträge
 
Delphi 12 Athens
 
#6

AW: Datei aus dem Papierkorb wiederherstellen

  Alt 28. Aug 2014, 00:28
Bei himitsu kann man sich darauf verlassen, dass bei Schlampereien in puncto Speicherlecks und Fehlerbehandlung nicht das Florett, sondern der Morgenstern oder gleich die Pumpgun rausgeholt wird!

Zitat:
Und die Try-Except sind das Schlimmste, was ich je gesehn hab.
Besser so ein Rekord als gar keiner...
Zitat:
...sorgt es dafür, daß der Nachfolgende Code (bis zum nächsten Except) nicht fehlerhaft ausgeführt wird.
Und genau das war mein Ziel, das Programm soll nicht knallen. Behandlung und Fehlerergründung und gar noch ausführliche Interaktion hierüber mit dem armen Anwender waren nicht mein Ziel, was soll es hier bringen? Durch den Rückgabewert weiß der Programmierer, dass es nicht geklappt hat, und was er dann tut und was er dem Anwender sagt, ist seine Sache.
Zitat:
SameFileName
Hm. Wenns die Funktion gibt, dann soll man sie wohl auch verwenden.

Hallo Dalai, du hast Recht.
  Mit Zitat antworten Zitat
Dejan Vu
(Gast)

n/a Beiträge
 
#7

AW: Datei aus dem Papierkorb wiederherstellen

  Alt 28. Aug 2014, 07:34
Bezüglich Fehlerbehandlung geht man eigentlich davon weg, den Anwender einer Methode durch Rückgabewerte über den Erfolg oder Misserfolg zu informieren. Stattdessen werden Exceptions eingesetzt. Der Grund ist einfach: Der Code ist lesbarer.
Delphi-Quellcode:
// Statt:
var
  r : TMethodResult;

begin
  r := ThisMethod();
  if r = Success then begin
    r := ThatMethod();
    if r = Success then
      DoSomething
    else
      ErrorHandling(r);
  end else
    ErrorHandling(r);
...
// Lieber
  Try
    ThisMethod();
    ThatMethod();
    DoSomething();
  Except
    On e:EMyMethodException do
      ErrorHandling(e);
  End
Wenn Du also noch eine EPapierkorb-Exception Klasse deklarierst und dann in dieser Exception den genauen Grund des Scheiterns lieferst, kann der Anwender die sehr elegante und -finde ich- einfacher lesbarere zweite Variante verwenden.

Und das mit der For-Schleife... Decke bitte den Mantel der Nächstenliebe über meinen Einwand. Danke hoika.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.326 Beiträge
 
Delphi 12 Athens
 
#8

AW: Datei aus dem Papierkorb wiederherstellen

  Alt 28. Aug 2014, 10:50
Besser so ein Rekord als gar keiner...
Oder besser nichts/weniger, als etwas Schlimmes.

* Auto mit Airbag
* Auto ohne Airbag
* Auto mit nicht funktionierendem Airbag, wo alle denken "ich brauch mich nicht anschnallen ... bin ja geschützt"

Ob ein bissl, ein bissl mehr oder der Superschutz, ist erstmal egal,
aber grob fahrlässigen Pfusch sollte man doch besser lassen.
Ein Therapeut entspricht 1024 Gigapeut.
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#9

AW: Datei aus dem Papierkorb wiederherstellen

  Alt 28. Aug 2014, 11:06
Und ich dachte immer, dass ein Airbag nur dann schützt, wenn man angeschnallt ist. Ohne Anschnallen ist das Verletzungsrisiko mit Airbag sogar höher.

http://www.unfallzeitung.de/zeitung/...e-alleskoenner
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort

 

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:27 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz