Seite 1 von 1

Probleme mit SHFileOperation_ (delete)

Verfasst: 14.10.2008 10:05
von Agent
Hallo.

Ich habe im Forum eine Routine gefunden, um Dateien in den Papierkorb zu verschieben:

Code: Alles auswählen

Procedure SK_RecycleFile(file$, ask.b=0, noerror.b=0, progress.b=1) ; PB3+4
  Define.l result

  ; #define FOF_SILENT      0x0004     // keine Angabe über  
  ;                                    // Fortschritt 
  ; #define FOF_NOERRORUI   0x0400     // keine Fehler-UI 
  ; #define FOF_ALLOWUNDO   0x0040     // für Papierkorb  
  ;                                    // erforderlich! 
  ; #define FOF_NOCONFIRMATION 0x0010  // keine Rückfrage

  SHFileOp.SHFILEOPSTRUCT 
  SHFileOp\pFrom        = @file$ 
  SHFileOp\wFunc        = #FO_DELETE 
  SHFileOp\fFlags       = #FOF_ALLOWUNDO
  
  If ask=0
    SHFileOp\fFlags | #FOF_NOCONFIRMATION
  EndIf
  If noerror=1
    SHFileOp\fFlags | $0400
  EndIf
  If progress=0
    SHFileOp\fFlags | #FOF_SILENT
  EndIf
  
  result = SHFileOperation_(SHFileOp) 
  
  CompilerIf #PB_Compiler_Debugger
    Debug "SK_Recyclefile: "+file$
    Debug "SK_Recyclefile: Result = "+Str(result)
  CompilerEndIf
  ; Liefert 0 (NULL) zurück wenn alles ok
  ; 1026 : Datei nicht vorhanden
  
  If result = 0
    result = #True
  EndIf
  
  ProcedureReturn result
EndProcedure 
Diese Routine funktioniert grundsätzlich. Nun möchte ich aber alle Dateien in einem Ordner löschen. Hierzu nutze ich eine kleine modifizierte Routine zum Einlesen der Dateien in eine Linklist:

Code: Alles auswählen


NewList ReadDirInfo$()

Procedure.l SK_ReadDirFast(Path.s="", SubDirs.b=1) ; PB4
  Shared ReadDirInfo$()
  Protected Dir.l
   
  If Right(Path,1)<>"\" : Path+"\" : EndIf
  Dir.l = ExamineDirectory(#PB_Any, Path, "")
  
  If IsDirectory(Dir)
    While NextDirectoryEntry(Dir)       

      name$ = DirectoryEntryName(Dir)
  
      If DirectoryEntryType(Dir) = #PB_DirectoryEntry_File
        AddElement(ReadDirInfo$())
        ReadDirInfo$() = Path + name$
        Debug "FILE: "+name$
      ElseIf DirectoryEntryType(Dir) = #PB_DirectoryEntry_Directory And SubDirs; Dir      
        Debug "DIR: "+name$
        If name$<>"." And name$<>".."
          SK_ReadDirFast(Path + name$, SubDirs)
        EndIf
      EndIf
     
    Wend
   
    FinishDirectory(Dir)  
  
  Else
    ProcedureReturn  #False 
  EndIf
  
  ProcedureReturn #True

EndProcedure 

Versuche ich nun über den Code:

Code: Alles auswählen

Debug sk_readdirfast("D:\Tests\Delete\")
ForEach  readdirinfo$()
  Debug SK_RecycleFile(readdirinfo$())
Next
alle Dateien löschen zu lassen, so werden nur ein Teil der Dateien gelöscht, alle anderen Enden mit einem Fehler 1026 von SHFileOperation. Die Dateien sind aber weder offen noch ähnliches, sie können über ein anderes beliebiges Programm gelöscht werden.

Hat jemand eine Idee?

Re: Probleme mit SHFileOperation_ (delete)

Verfasst: 14.10.2008 10:47
von Kiffi
habe mal ein wenig recherchiert. Dieser Fehler scheint öfters aufzutreten.
Und zwar anscheinend immer sporadisch (sprich: einige Dateien werden
gelöscht, andere wiederum nicht). Das Problem wird wohl darin liegen, dass
pFrom und pTo Doppelnull-terminiert sein müssen.

(In Deinem Fall natürlich nur pFrom)

Weitere Infos im Posting von Kurzer:
http://www.purebasic.fr/german/viewtopi ... 055#154055

Grüße ... Kiffi

Verfasst: 14.10.2008 18:56
von Agent
Hi Kiffi.

DAnke für die Recherche. Ist mir noch nie untergekommen.
Werde es aber mal testen!

Verfasst: 14.10.2008 19:03
von ts-soft
Es kann eine Liste von Files übergeben werden, alle 0 terminiert, der letze
00 (WC) terminiert. Wenn man nur einen übergibt, ist dies der letzte.
Die Wahrscheinlichkeit das sich im Speicher hinter diesem String eine
weitere 0 befindet ist groß, aber wie man sieht nicht immer wahr.

Verfasst: 15.10.2008 13:13
von Agent
Hallo nochmal.

Habs getestet. Funktioniert wunderbar mit Dateien. Leider nicht mit Verzeichnissen. Was muss ich dabei beachten?

Verfasst: 13.11.2008 14:10
von Agent
*Nochmal nachfrag*

Leider funzt das nicht mit Ordnern, gibt es hier was spezielles zu beachten?

Vorab danke.

Verfasst: 13.11.2008 14:13
von ts-soft
Agent hat geschrieben:*Nochmal nachfrag*

Leider funzt das nicht mit Ordnern, gibt es hier was spezielles zu beachten?

Vorab danke.
Keine Ahnung, liegt wohl an den Ordnernamen. Wahrscheinlich ohne
Backslash, aber mußte selber testen.

Verfasst: 13.11.2008 14:20
von Kiffi
Agent hat geschrieben:Leider funzt das nicht mit Ordnern, gibt es hier was spezielles zu beachten?
funktioniert u.U. nur mit leeren Ordnern. Kannst Du das mal (neben dem
Tipp von Thomas) ausprobieren?

Grüße ... Kiffi

Verfasst: 14.11.2008 14:35
von Agent
Hallo.

Nein, lag nicht an den Backslashs. Habe das Problem aber gelöst. Thomas hat mich aber auf die Idee gebracht mit der Doppel-NULL-Terminierung.

Leider ist es damit nicht getan einfach ZWEI NULL-Bytes hintendran zu hängen, denn dann gehen zwar die Ordner, aber nicht mehr die Dateien. Also habe ich kurzum die Proc so gestaltet, das bei DAteien EINE NULL und bei Ordnern ZWEI NULLEN angehängt werden.

Die fertige Proc sieht dann so aus und läuft bisher auch gut:
Zu beachten ist hierbei natürlich, das ein Ordner in JEDEM Fall mit einem Backslash endet - dürfte aber logisch sein wenn man sich den Code betrachtet.

Code: Alles auswählen


Procedure SK_Recycle(file$, ask.b=0, noerror.b=0, silent.b=0) ; PB3+4
  Define.l result

  ; #define FOF_SILENT      0x0004     // keine Angabe über  
  ;                                    // Fortschritt 
  ; #define FOF_NOERRORUI   0x0400     // keine Fehler-UI 
  ; #define FOF_ALLOWUNDO   0x0040     // für Papierkorb  
  ;                                    // erforderlich! 
  ; #define FOF_NOCONFIRMATION 0x0010  // keine Rückfrage
  #FOF_NOERRORUI = $400
  
  If Right(file$, 1) = "\"
    Debug "adding to dir 2 ZEROS"
    file$ =  file$ + "  "
    PokeB(@file$ + Len(file$)-2, 0)  
    PokeB(@file$ + Len(file$)-1, 0)  
  Else
    Debug "adding to FILE a ZERO"
    file$ =  file$ + " "
    PokeB(@file$ + Len(file$)-1, 0)     
  EndIf
  

  SHFileOp.SHFILEOPSTRUCT 
  SHFileOp\pFrom        = @file$ 
  SHFileOp\wFunc        = #FO_DELETE 
  SHFileOp\fFlags       = #FOF_ALLOWUNDO
  
  If ask=0
    SHFileOp\fFlags | #FOF_NOCONFIRMATION
  EndIf
  If noerror=1
    SHFileOp\fFlags | #FOF_NOERRORUI
  EndIf
  If silent=1
    SHFileOp\fFlags | #FOF_SILENT
  EndIf
  
  result = SHFileOperation_(SHFileOp) 
  
  CompilerIf #PB_Compiler_Debugger
    If Right(file$, 1) = "\"
      Debug "SK_Recycle: DIR: "+file$
    Else
      Debug "SK_Recycle: FILE: "+file$
    EndIf 
  CompilerEndIf
  ; Liefert 0 (NULL) zurück wenn alles ok
  ; 1026 : Datei nicht vorhanden
  
  If result = #S_OK
    result = #True
  EndIf
  
  ProcedureReturn result
EndProcedure 

Verfasst: 14.11.2008 14:35
von Agent
ADD:

Als Optimierung könnte man natürlich noch abfragen ob es sich um ein Ordner oder eine Datei handelt ;-)