Here is some code that should work but doesn’t… And this is the 3rd iteration of the code (it is the cleanest that remains). The other versions I have beat on so much they don’t look like reasonable code anymore.
the goal of the method is to delete a folderitem. If the said folderitem is a directory, it will delete the contents prior to deleting itself. As folderitem.delete won’t delete itself and all subdirectories/files.
Sub deleteFolderitem(deleteItem as folderitem)
if deleteItem = NIL then return // cant delete a NIL folderitem
if not deleteItem.Exists then return // it doesnt exist so we cant delete it.
if deleteitem.Directory then
// its a directory/folder
if deleteItem.Count > 0 then
// we have subfolders and/or files in the directory that we need to delete first
// going to use MBS plugins for getting the list of files(filesMBS) and directories(folderMBS)
for each oFile as folderitem in deleteItem.FilesMBS
oFile.delete
if oFile.LastErrorCode > 0 then
// we have an error on the file delete
System.DebugLog "oFile.LastErrorCode = " + cstr( oFile.LastErrorCode ) + " for " + oFile.ShellPath
end if
next
// no the directories
for each oDir as folderitem in deleteItem.FoldersMBS
// call myself(the method) recurisively to get the subdirectory clear.
deleteFolderitem( oDir )
// now that we are in theory empty we can delete the directory.
oDir.delete
if oDir.LastErrorCode > 0 then
// we have an error on the file delete
System.DebugLog "oDir.LastErrorCode = " + cstr( oDir.LastErrorCode ) + " for " + oDir.ShellPath
end if
next
end if
deleteItem.delete
if deleteItem.LastErrorCode > 0 then
// we have an error on the directory delete
System.DebugLog "deleteItem.LastErrorCode = " + cstr( deleteItem.LastErrorCode ) + " for " + deleteItem.ShellPath
end if
else
// its a file
deleteItem.delete
if deleteItem.LastErrorCode > 0 then
// we have an error on the file delete
System.DebugLog "deleteItem.LastErrorCode = " + cstr( deleteItem.LastErrorCode ) + " for " + deleteItem.ShellPath
end if
end if
End Sub
I get either error code 101 (file not found) or 104 (file in use). the later is odd since the only thing that can be using these files are the app itself as it created them.
This is the code I wrote for this purpose. Perhaps this will help? Otherwise, at what point are you getting the errors?
Function Items_MTC(Extends f As FolderItem, includeInvisibles As Boolean = True) As FolderItem()
dim r() as FolderItem
if f <> nil and f.Exists and f.Directory then
dim thisItem as FolderItem
dim cnt as integer = f.Count
// Do this as two separate loops to save some cycles
if includeInvisibles then
redim r( cnt - 1 )
for i as integer = 1 to cnt
thisItem = f.Item( i )
r( i - 1 ) = thisItem
next i
else // Have to check for visibility
for i as integer = 1 to cnt
thisItem = f.Item( i )
if thisItem.Visible then
r.Append thisItem
end if // isVisible
next i
end if // includeInvisibles
end if // f <> nil and f.Exists and f.Directory
return r
End Function
Function DeleteContentsOfFolder_MTC(Extends baseFolder As FolderItem) As Integer
// Recursively deletes the contents of a folder, but keeps the folder in place.
// If there is a problem anywhere along the way, returns an error code.
dim errorCode as integer = 0
if not baseFolder.Exists or not baseFolder.Directory then
return errorCode
end if
dim queue() as FolderItem = baseFolder.Items_MTC
while queue.Ubound <> -1
dim thisItem as FolderItem = queue.Pop
if thisItem.Directory then
dim subItems() as FolderItem = thisItem.Items_MTC
if subItems.Ubound <> -1 then
queue.Append thisItem
thisItem = nil
for each f as FolderItem in subItems
queue.Append f
next
end if
end if
if thisItem <> nil and thisItem.Exists then
thisItem.Delete
errorCode = thisItem.LastErrorCode
if errorCode <> 0 then
exit while
end if
end if
wend
return errorCode
End Function
Function DeleteRecursive_MTC(Extends f As FolderItem) As Integer
// Deletes the contents of a folder, then the folder itself.
// If there is an error along the way, returns the code
dim errorCode as integer = 0
if not f.Exists then return errorCode
errorCode = f.DeleteContentsOfFolder_MTC()
if errorCode = 0 then
f.Delete
errorCode = f.LastErrorCode
end if
return errorCode
End Function
I use this function without any problem in several project.
Function DeleteEntireFolder(theFolder as FolderItem, continueIfErrors as Boolean = false) As Integer
// Returns an error code if it fails, or zero if the folder was deleted successfully
dim returnCode, lastErr, itemCount as integer
dim files(), dirs() as FolderItem
if theFolder = nil or not theFolder.Exists() then
return 0
end if
// Collect the folders contents first.
// This is faster than collecting them in reverse order and deleting them right away!
itemCount = theFolder.Count
for i as integer = 1 to itemCount
dim f as FolderItem
f = theFolder.TrueItem( i )
if f <> nil then
if f.Directory then
dirs.Append f
else
files.Append f
end if
end if
next
// Now delete the files
for each f as FolderItem in files
f.Delete
lastErr = f.LastErrorCode // Check if an error occurred
if lastErr <> 0 then
if continueIfErrors then
if returnCode = 0 then returnCode = lastErr
else
// Return the error code if any. This will cancel the deletion.
return lastErr
end if
end if
next
redim files(-1) // free the memory used by the files array before we enter recursion
// Now delete the directories
for each f as FolderItem in dirs
lastErr = DeleteEntireFolder( f, continueIfErrors )
if lastErr <> 0 then
if continueIfErrors then
if returnCode = 0 then returnCode = lastErr
else
// Return the error code if any. This will cancel the deletion.
return lastErr
end if
end if
next
if returnCode = 0 then
// Were done without error, so the folder should be empty and we can delete it.
theFolder.Delete
returnCode = theFolder.LastErrorCode
end if
return returnCode
End Function
Pietro’s code is what I did put into the docs a while ago, I believe. It’s been tested and designed for optimal performance and handling all error cases.
Everyone here is an update. For some unknown freaking reason neither my code nor any of yalls code works (I tried all the code in this thread). I am trying to delete a directory and a tar file that the app created itself. I get an errorcode 104 which means the file is in use.
Now here is the kick in the pants. In the same place I call the delete the folderitem method, I shell out and do a “/bin/sh -R /shell/path/to/folderitem” and it works 100% of the time. so the filesystem nor O/S has the handle on the foldereitem. It must be something within Xojo itself. It is a Xojo Console app.
Scott, you say your app created the directory and tar file. Are you sure you have actually closed all connections to the file? If there is still one open the app can’t delete it. I’d check to make sure the file is actually closed.
Also, don’t forget to close and/or nil the FolderItem for the file AND the directory to ensure your app doesn’t have connection to them. Either will prevent deletion.
there isn’t a folderitem.close method. and if I NIL the folderitem, how do I do a folderitem.delete on it later? And if the (Xojo) app still had the file/directory open, then why does a /bin/rm -R /path/to/foldteritem work?
[quote=194565:@scott boss]Everyone here is an update. For some unknown freaking reason neither my code nor any of yalls code works (I tried all the code in this thread). I am trying to delete a directory and a tar file that the app created itself. I get an errorcode 104 which means the file is in use.
Now here is the kick in the pants. In the same place I call the delete the folderitem method, I shell out and do a “/bin/sh -R /shell/path/to/folderitem” and it works 100% of the time. so the filesystem nor O/S has the handle on the foldereitem. It must be something within Xojo itself. It is a Xojo Console app.
Not sure if I need to open a bug report or not.[/quote]
Xojo calls OS API’s which use a different mechanism than what rm uses to remove the file
So they can vary in what they allow and do
Hmm. … was looking for a smart way to remove and entire tree. Wrote my own after checking this forum first.
[code]Private Sub EmptyThisFolder(f as FolderItem)
// empty entire folder (remove all files and subfolders)
Try
If f.Directory Then
If f.Count > 0 Then
Do
Dim g As FolderItem = f.Item(1)
If g <> Nil Then
If g.Directory Then
EmptyThisFolder(g) // recursive
g.Delete
Else
g.Delete
End If
Else
Exit
End If
Loop
End If
End If
Catch err As RuntimeException
RaiseEvent FileError(“Could not remove file or directory”)
End Try
The recursive way of deleting folders will fail if the structure is going deep (you’ll get a StackOverflow exception).
There are better methods which avoid recursion (basically just add each encountered folder to an array and empty every folder you find in this array).