why can't I delete a folderitem and all subdirectories/files... wrote a method for it but it don't w

  1. 5 years ago

    scott b

    14 May 2015 Pre-Release Testers, Xojo Pro local coffee shop

    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

    thanks... I know that I am doing something stupid.

  2. scott b

    14 May 2015 Pre-Release Testers, Xojo Pro local coffee shop

    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.

  3. Kem T

    14 May 2015 Pre-Release Testers, Xojo Pro, XDC Speakers Connecticut

    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
  4. Pietro B

    14 May 2015 Pre-Release Testers, Xojo Pro Europe (Swiss, Chiasso)

    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 folder‘s 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
        // We‘re 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
  5. Kem T

    14 May 2015 Pre-Release Testers, Xojo Pro, XDC Speakers Connecticut

    Ack! That's a bug in my code. It should be TrueItem instead of Item. Thanks Pietro.

  6. Thomas T

    14 May 2015 Pre-Release Testers, Xojo Pro Europe (Germany, Munich)

    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.

  7. Pietro B

    14 May 2015 Pre-Release Testers, Xojo Pro Europe (Swiss, Chiasso)

    It 's true. As I wrote, I use this function. I did not say that I wrote it. So thanks Thomas also from me. ;-)

  8. Christian S

    14 May 2015 Pre-Release Testers, Xojo Pro, XDC Speakers, Third Party Store Germany

    @Scott boss:
    You should use TrueFilesMBS and TrueFoldersMBS instead of the variants without true.

  9. 4 years ago

    scott b

    15 Jun 2015 Pre-Release Testers, Xojo Pro local coffee shop

    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.

  10. Eli O

    is not verified 15 Jun 2015 Europe (Berlin, Germany)

    @scott b "/bin/sh -R /shell/path/to/folderitem"

    Shouldn't there be a shell command like rmdir in this line?

  11. Dale A

    16 Jun 2015 San Diego, California, USA

    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.

  12. scott b

    16 Jun 2015 Pre-Release Testers, Xojo Pro local coffee shop

    @Dale A 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?

    sorry if I am being dense here.

  13. Tim H

    16 Jun 2015 Pre-Release Testers Portland, OR USA
    Edited 4 years ago

    Use the copy constructor.

    f2 = New FolderItem(f1)
    f1 = nil
    f2.Delete

    Although, I wouldn't expect a folderitem to be the culprit. Have you nil-ed out all streams?

  14. Norman P

    16 Jun 2015 Xojo Inc, Pre-Release Testers, Xojo Pro Seeking work. npalardy@great-w...

    @scott b 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.

    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

  15. 7 days ago

    Joost R

    Nov 6 Pre-Release Testers, Xojo Pro The Netherlands

    Hmm. .. was looking for a smart way to remove and entire tree. Wrote my own after checking this forum first.

    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
      
    End Sub
  16. Michael D

    Nov 6 Pre-Release Testers, Xojo Pro
    Edited 7 days ago

    One should be careful about whether you are using .Item() or .TrueItem() depending on whether or not alias files should be followed.

  17. Michel B

    Nov 6 Pre-Release Testers, Xojo Pro RubberViews.com
    Edited 7 days ago

    Any reason why you did not simply use the example method at https://web.archive.org/web/20190324041130/http://docs.xojo.com/FolderItem.delete

    or API 2 http://docs.xojo.com/FolderItem.Remove ?

    I have been using it for years and it works flawlessly. Unless a file is locked, of course.

  18. 6 days ago

    Joost R

    Nov 7 Pre-Release Testers, Xojo Pro The Netherlands

    @Michel B Any reason why you did not simply use the example method

    Was not aware of the official sample so just started writing my own. At least, as I see now, my code is much smaller and seems to work perfect also.

  19. Beatrix W

    Nov 7 Pre-Release Testers, Third Party Store Europe (Germany)

    The docs say that .remove deletes a "file or folder". Then there is an example to recursively delete a folder. With the old API.

or Sign Up to reply!