Page 1 of 1

RecycleFile (Windows)

Posted: Sat Aug 17, 2002 5:40 am
by BackupUser
Restored from previous forum. Originally posted by PB.

UPDATE: See corrected code further down (dated Mon Feb 11, 2008).
The example in this first particular post is faulty and not 100% reliable.



This procedure lets you "delete" files by sending them to the Recycle Bin (also
known as the Trash Can) instead of permanently deleting them as DeleteFile does.
Note that there is a bit of a delay after calling this procedure to the time the
file(s) is recycled... I don't know if this can be sped up, but I doubt it. You
can use this with wildcards (*?) too, just like DeleteFile does. Enjoy!


; RecycleFile by PB -- do what you want with it. :)
; Usage: RecycleFile(file$)
; Same as DeleteFile() except files go to the bin.
;
Procedure RecycleFile(file$)
SHFileOp.SHFILEOPSTRUCT
SHFileOp\pFrom=@file$
SHFileOp\wFunc=#FO_DELETE
SHFileOp\fFlags=#FOF_ALLOWUNDO
SHFileOperation_(SHFileOp)
EndProcedure


PB - Registered PureBasic Coder


Edited by - PB on 17 August 2002 07:01:53

Addendum: RecycleFile (Windows)

Posted: Tue May 11, 2004 8:22 am
by Andy
One little thing I think should be corrected here - Microsoft write for the pFrom-value:
An additional NULL character must be appended to the end of the final name to indicate the end of pFrom.
So we need two NULLs at the end of the string. I have do this so (not so elegant, could be possibly more efficient - but it works :wink:):

Code: Select all

Procedure _RecycleFile(file$)
  ; RecycleFile by PB -- do what you want with it.  
  ; Usage: RecycleFile(file$)
  ; Same as DeleteFile() except files go to the bin.
  ; Modified by Andy (PB 3.91)
  s=Len(file$)+3
  MemoryID=AllocateMemory(s)
  For i=s-3 To s-1
    PokeB(MemoryID+i,0)
  Next
  PokeS(MemoryID,file$)
  SHFileOp.SHFILEOPSTRUCT
  SHFileOp\pFrom=MemoryID
  SHFileOp\wFunc=#FO_DELETE
  SHFileOp\fFlags=#FOF_ALLOWUNDO | #FOF_SILENT
  result = SHFileOperation_(@SHFileOp)
  FreeMemory(MemoryID)
  ProcedureReturn result
EndProcedure
Andy

12.5.04 Edit: Some little corrections... :wink:

Re: Addendum: RecycleFile (Windows)

Posted: Sat Feb 09, 2008 11:31 am
by PB
A belated thanks to Andy for fixing my tip: I needed this fix today. :)

Posted: Sat Feb 09, 2008 2:31 pm
by MikeB
How about -

Code: Select all

Procedure RecycleFile(file$)
        SHFileOp.SHFILEOPSTRUCT
        SHFileOp\pFrom=@file$
        SHFileOp\wFunc=#FO_DELETE
        SHFileOp\fFlags=#FOF_ALLOWUNDO | #FOF_NOCONFIRMATION ; without #FOF_NOCONFIRMATION you get a messagerequester asking to confirm sending to recycle bin
        SHFileOperation_(SHFileOp)
EndProcedure
I've been using this for years, is there something I've missed?

Posted: Sun Feb 10, 2008 1:06 am
by PB
@MikeB: What you posted is basically the same code as my tip at the top of
this thread. It doesn't always work, even though I too thought it did. This is
because the filename MUST end with 2 x Chr(0) to work 100% correctly,
because Windows uses Chr(0) to separate multiple filenames. So an extra
Chr(0) is needed to signify the end of the file list.

In other words, you can recycle 2 files with one string:

file$ = "Name1"+Chr(0)+"Name2"+Chr(0)+Chr(0)

The last Chr(0) is needed, even if you only use one filename. I suffered this
problem yesterday, where the tip I gave (and you gave above) just wouldn't
recycle the files I was giving it. When I used Andy's tip, which adds the extra
required Chr(0), it all worked perfectly. I highly recommend you use it too.

In my own twisted coding way I modified Andy's addition to look like the
following, because a return value of 0 for SHFileOperation means success,
not failure. So the code below returns 0 for failure, and 1 for success.

Code: Select all

Procedure RecycleFile(file$)
  #FOF_NOERRORUI=$400 ; PureBasic doesn't recognise this constant (as of v4.20 Beta 2).
  s=Len(file$)+3 : m=AllocateMemory(s) : For p=s-3 To s-1 : PokeB(m+p,0) : Next : PokeS(m,file$)
  SHFileOp.SHFILEOPSTRUCT : SHFileOp\pFrom=m : SHFileOp\wFunc=#FO_DELETE
  SHFileOp\fFlags=#FOF_ALLOWUNDO|#FOF_NOERRORUI : ok=SHFileOperation_(SHFileOp)
  If ok=0 : ok=1 : Else : ok=0 : EndIf : FreeMemory(m)
  ProcedureReturn ok
EndProcedure

Posted: Sun Feb 10, 2008 10:19 am
by akj
Surely the code:

Code: Select all

For p=s-3 To s-1 : PokeB(m+p,0) : Next
is redundant as the documentation for AllocateMemory() states that the memory area will be initialised with nulls.

Posted: Mon Feb 11, 2008 4:52 am
by PB
> Surely [For/Next] is redundant as the documentation for AllocateMemory()
> states that the memory area will be initialised with nulls

Correct! :) Here is the amended code, now also with error-checking in case
AllocateMemory couldn't be done. Works 100% perfectly on all files I tested.

Code: Select all

Procedure RecycleFile(file$)
  #FOF_NOERRORUI=$400
  m=AllocateMemory(Len(file$)+2)
  If m
    PokeS(m,file$) : SHFileOp.SHFILEOPSTRUCT : SHFileOp\pFrom=m : SHFileOp\wFunc=#FO_DELETE
    SHFileOp\fFlags=#FOF_ALLOWUNDO|#FOF_NOERRORUI : ok=SHFileOperation_(SHFileOp) : FreeMemory(m)
    If ok=0 : ok=1 : Else : ok=0 : EndIf
  EndIf
  ProcedureReturn ok
EndProcedure

Posted: Mon Feb 11, 2008 2:59 pm
by MikeB
Thanks for the explanation, I understand what is going on now, although as far as I know it has worked in the past. However since I normally replace the file with a longer version, hence overwriting the original, it would not be obvious if it had not finished in the trashcan unless I wanted to recover it and so far I haven't. So I have been assuming it was working because it did a few years ago when I tested it! :oops:

Posted: Mon Feb 11, 2008 8:46 pm
by PB
> I have been assuming it was working because it did a few years ago when
> I tested it! :oops:

Same here. It did work for me in the past, too. You're not alone. But like I said,
the other day when I used it in an app, it didn't, so I don't know if PureBasic is
now doing something "correctly" or what. :)

Re:

Posted: Sat May 23, 2015 3:43 am
by Blue
PB wrote:> [...]
AllocateMemory couldn't be done. Works 100% perfectly on all files I tested.

Code: Select all

Procedure RecycleFile(file$)
  #FOF_NOERRORUI=$400
  m=AllocateMemory(Len(file$)+2)
  If m
    PokeS(m,file$) : SHFileOp.SHFILEOPSTRUCT : SHFileOp\pFrom=m : SHFileOp\wFunc=#FO_DELETE
    SHFileOp\fFlags=#FOF_ALLOWUNDO|#FOF_NOERRORUI : ok=SHFileOperation_(SHFileOp) : FreeMemory(m)
    If ok=0 : ok=1 : Else : ok=0 : EndIf
  EndIf
  ProcedureReturn ok
EndProcedure
For this to work in Unicode, I think StringByteLength(file$) MUST replace Len(file$) in the 2nd line of the Procedure :

Code: Select all

m=AllocateMemory(StringByteLength(file$)+4)
I was experiencing random crashes with this code until I started using StringByteLength()

Re: RecycleFile (Windows)

Posted: Sat May 23, 2015 5:29 am
by Danilo
Yes, or you use sizeof() combined with Len():

Code: Select all

Procedure RecycleFile(file$)
    Protected m, result, SHFileOp.SHFILEOPSTRUCT
    m = AllocateMemory( ( Len(file$)+2 ) * SizeOf(Character) )
    If m
        PokeS(m,file$)
        SHFileOp\pFrom  = m
        SHFileOp\wFunc  = #FO_DELETE
        SHFileOp\fFlags = #FOF_ALLOWUNDO|#FOF_NOERRORUI
        result = SHFileOperation_(SHFileOp)
        FreeMemory(m)
        ProcedureReturn Bool(result = 0)
    EndIf
EndProcedure

Re: RecycleFile (Windows)

Posted: Sat May 23, 2015 5:45 am
by Blue
Danilo wrote:Yes, or you use sizeof() combined with Len():

Code: Select all

Procedure RecycleFile(file$)
    [...]
    m = AllocateMemory( ( Len(file$)+2 ) * SizeOf(Character) )
    [...]
EndProcedure
Great ! I never could think of anything really useful to do with the SizeOf() instruction.
But I see now that it can be cleverly used. :shock:
Thank you, Danilo.
This is turning out to be a good day : I learned something new ! :D