Sign in to follow this  
Followers 0
Chetwood

DirRemove($deldir, 1) does not delete all files

15 posts in this topic

Well, I've finally managed to get my new version of MultiShrink out which is a small tool to enable batch processing with DVD Shrink. I've added a delete option that deletes the source dir once the encoding is done on that particular DVD. Problem is that in some not reproducible cases one file (always the last vob of a certain DVD) is not deleted and thus the source dir not removed.

I've got no idea what's causing this cause the delete function is the last one to be executed after having

- closed all open DVDs in that particular instance of DVD Shrink

- closed that instance itself

so that there should be no files open from that source dir whatsoever. Any idea how can I track this down?


MultiMakeMKV: batch processing for MakeMKV (Win)MultiShrink: batch processing for DVD ShrinkOffizieller Übersetzer von DVD Shrink deutsch

Share this post


Link to post
Share on other sites



Can you delete the file in Windows?

Share this post


Link to post
Share on other sites

Can you delete the file in Windows?

<{POST_SNAPBACK}>

Well, I haven't stood by the moment the DVD was encoded so I did not try to delete it manually the moment this instance of DVD Shrink was closed. However, when I got back to my PC in the morning I could delete the whole dir without any problems.

I'm afraid it's similar to the effect you sometimes experience when installing software. The program's just been installed but you cannot yet delete the 'setup.exe' cause windows still got it locked before cleaning it from memory or something.


MultiMakeMKV: batch processing for MakeMKV (Win)MultiShrink: batch processing for DVD ShrinkOffizieller Übersetzer von DVD Shrink deutsch

Share this post


Link to post
Share on other sites

That is a good possibility. I know this probably is not a good way to do it, but I would put in a few seconds of sleep before the delete process is called. See if that helps. I dont know of any other way to really debug it. You could also after it is deleted do a FileExists() and if it does Delete it again. That might work :-?

JS


AutoIt Links

File-String Hash Plugin Updated! 04-02-2008 Plugins have been discontinued. I just found out.

ComputerGetInfo UDF's Updated! 11-23-2006

External Links

Vortex Revolutions Engineer / Inventor (Web, Desktop, and Mobile Applications, Hardware Gizmos, Consulting, and more)

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

Try deleting your file(s)/folder(s) with this:

Those are funcs that allow deleting a file boottime if they can't deleted outright.

;This is a func that is inside Run!, why not use it?
; http://crimsonfan.altervista.org

;_DeleteFolder()
_DeleteFiles()

Exit
Func _DeleteFiles()
   Local $sSelection, $aSelection, $c, $cDel = 0
   $sSelection = FileOpenDialog('What file(s) do you want to delete?', @HomeDrive, 'All (*)', 5)
   Select 
      Case $sSelection = 1
         Return 0
      Case StringInStr($sSelection, '|')
         $aSelection = StringSplit($sSelection, '|')
         If StringRight($aSelection[1], 1) <> '\' Then $aSelection[1] = $aSelection[1] & '\'
         For $c = 2 To $aSelection[0]
            $cDel = $cDel + _DeleteFile($aSelection[1] & $aSelection[$c])
         Next
      Case Else;The user selected only a file.
         $cDel = _DeleteFile($sSelection)
   EndSelect
   Return $cDel
EndFunc  ;==>_DeleteFiles

Func _DeleteFolder()
   Local $sSelection, $iDelDir, $aFiles, $c, $cDel = 0
   $iDelDir = MsgBox(32 + 3, 'Question.', 'Do you want to delete also the folder itself?' & @LF & @LF & 'No, please just delete the files/folders inside it.' & @LF & 'Yes, erase also the folder after emptying it.')
   If $iDelDir = 2 Then Return 0
  ;6 = Yes, 7 = No
   $sSelection = FileSelectFolder('What folder do you want to delete?', @HomeDrive, 4)
   If @error Then Return 0
   If StringRight($sSelection, 1) <> '\' Then $sSelection = $sSelection & '\'
   $aFiles = _FileSearch($sSelection, 1)
   For $c = 1 To $aFiles[0]
      If Not StringInStr(FileGetAttrib($aFiles[$c]), 'd') Then
         $cDel = $cDel + _DeleteFile($aFiles[$c])
      EndIf;If $cDel is still 0 then all files has been deleted already,
    ;      so the empty folders can be already removed too.
   Next
   Select
      Case $iDelDir = 6 And $cDel <> 0
         If Not ($iOS = 3) Then
            RegWrite('HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce', $sSelection, 'reg_sz', @ComSpec & ' /c rd /s/q "' & $sSelection & '"')
         Else
            RegWrite('HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce', $sSelection, 'reg_sz', @ComSpec & ' /c deltree /y "' & $sSelection & '"')
         EndIf
      Case $iDelDir = 6 And $cDel = 0;The folder is deleted outright.
         DirRemove($sSelection, 1)
      Case $iDelDir = 7 And $cDel = 0
         DirRemove($sSelection, 1)
         DirCreate($sSelection)
      Case $iDelDir = 7 And $cDel <> 0
         If Not ($iOS = 3) Then
            RegWrite('HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce', $sSelection & '1', 'reg_sz', @ComSpec & ' /c rd /s/q "' & $sSelection & '"')
            RegWrite('HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce', $sSelection & '2', 'reg_sz', @ComSpec & ' /c md "' & $sSelection & '"')
         Else
            RegWrite('HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce', $sSelection, 'reg_sz', @ComSpec & ' /c deltree /y "' & $sSelection & '."')
         EndIf
   EndSelect
   Return $cDel
EndFunc  ;==>_DeleteFolder

Func _DeleteFile($sFile)
   
  ; Description:      Try to delete a file, if it fails it deletes it reboot time.
  ; Syntax:           _DeleteFile( $sFilename )
  ; Parameter(s):     $sFilename - The name of the file to delete. No wildcards.
  ; Return Value(s):  -1 The file does not exist
  ;                    0 The file has already been deleted
  ;                    1 The file will be deleted boot time
  ; Author(s):        Ezzetabi ezzetabi@katamail.com
   
   Local $sPending, $sFile, $iLFpos
   If StringInStr($sFile, "*") Or StringInStr($sFile, "?") Then Return -2
   If Not StringInStr($sFile, "\") Then $sFile = @WorkingDir & "\" & $sFile;Adds the full path
   
   If Not FileExists($sFile) Then Return -1
   If FileDelete($sFile) Then Return 0
   
  ;If the code arrives here it means that the file is in-use and so
  ;it will be deleted at the reboot.
   
   If @OSTYPE = "WIN32_NT" and @OSVersion <> 'WIN_NT4' Then;The Kernel is W2000
      $sPending = RegRead("HKLM\System\CurrentControlSet\Control\Session Manager", _
            "PendingFileRenameOperations")
      If $sPending = "" Then
         RegWrite("HKLM\System\CurrentControlSet\Control\Session Manager", _
               "PendingFileRenameOperations", "reg_multi_sz", _
               "\??\" & $sFile & @LF)
      Else
         $iLFpos = StringInStr($sPending, @LF, 0, -1)
         Select
            Case $iLFpos = 0 Or StringMid($sPending, $iLFpos - 1, 1) = @LF;Existing operation is a deletion
               RegWrite("HKLM\System\CurrentControlSet\Control\Session Manager", _
                     "PendingFileRenameOperations", "reg_multi_sz", $sPending & @LF & @LF & "\??\" & _
                     $sFile & @LF)
            Case StringMid($sPending, $iLFpos - 1, 1) <> @LF;Existing operation is a rename
               RegWrite("HKLM\System\CurrentControlSet\Control\Session Manager", _
                     "PendingFileRenameOperations", "reg_multi_sz", $sPending & @LF & "\??\" & _
                     $sFile & @LF)
         EndSelect
      EndIf
      
   Else;The Kernel is Win9x/Nt
      $sFile = FileGetShortName($sFile)
      $sPending = FileRead(@WindowsDir & "\wininit.ini", FileGetSize(@WindowsDir & "\wininit.ini"))
      If @error Then;The file wininit.ini DOES NOT exist.
         FileWrite(@WindowsDir & "\wininit.ini", "[rename]" & @CRLF & _
               "NUL=" & $sFile)
      Else              ;The file wininit.ini EXISTS
         Local $iPos, $sOldFile
         $iPos = StringInStr($sPending, "[rename]")
         If $iPos = 0 Then;The [Rename] section is not there.
            FileWrite(@WindowsDir & "\wininit.ini", @CRLF & "[rename]" & @CRLF & _
                  "NUL=" & $sFile);... So it is just added at the end.
         Else;The section [rename] is there
            $iPos = $iPos + 9;(7 of the word [rename] and 2 of @crlf)
            $sOldFile = StringRight($sPending, StringLen($sPending) - $iPos)
            $sPending = StringTrimRight($sPending, StringLen($sPending) - $iPos)
          ;$sPending contain the whole wininit.ini, I removed the right part after [rename]
          ;after coping it in $sOldFile
            $sPending = $sPending & "NUL=" & $sFile & @CRLF & $sOldFile
          ;I add the line for deleting. And re-add the right part removed.
            FileDelete(@WindowsDir & "\wininit.ini")
            FileWrite(@WindowsDir & "\wininit.ini", $sPending)
          ;I recreate the file
         EndIf
      EndIf
   EndIf
   Return 1
EndFunc  ;==>_DeleteFile

Func _FileSearch($sIstr, $bSF)
  ; $bSF = 1 means looking in subfolders
  ; $sSF = 0 means looking only in the current folder.
  ; An array is returned with the full path of all files found. The pos [0] keeps the number of elements.
   Local $sIstr, $bSF, $sCriteria, $sBuffer, $iH, $iH2, $sCS, $sCF, $sCF2, $sCP, $sFP, $sOutPut = '', $aNull[1]
   $sCP = StringLeft($sIstr, StringInStr($sIstr, '\', 0, -1))
   If $sCP = '' Then $sCP = @WorkingDir & '\'
   $sCriteria = StringTrimLeft($sIstr, StringInStr($sIstr, '\', 0, -1))
   If $sCriteria = '' Then $sCriteria = '*.*'
   
  ;To begin we seek in the starting path.
   $sCS = FileFindFirstFile($sCP & $sCriteria)
   While $sCS <> - 1
      $sCF = FileFindNextFile($sCS)
      If @error Then
         FileClose($sCS)
         ExitLoop
      EndIf
      If $sCF = '.' Or $sCF = '..' Then ContinueLoop
      $sOutPut = $sOutPut & $sCP & $sCF & @LF
   Wend
   
  ;And after, if needed, in the rest of the folders.
   If $bSF = 1 Then
      $sBuffer = @CR & $sCP & '*' & @LF;The buffer is set for keeping the given path plus a *.
      Do 
         $sCS = StringTrimLeft(StringLeft($sBuffer, StringInStr($sBuffer, @LF, 0, 1) - 1), 1);current search.
         $sCP = StringLeft($sCS, StringInStr($sCS, '\', 0, -1));Current search path.
         $iH = FileFindFirstFile($sCS)
         While $iH <> - 1
            $sCF = FileFindNextFile($iH)
            If @error Then
               FileClose($iH)
               ExitLoop
            EndIf
            If $sCF = '.' Or $sCF = '..' Then ContinueLoop
            If StringInStr(FileGetAttrib($sCP & $sCF), 'd') Then
               $sBuffer = @CR & $sCP & $sCF & '\*' & @LF & $sBuffer;Every folder found is added in the begin of buffer
               $sFP = $sCP & $sCF & '\';                            for future searches
               $iH2 = FileFindFirstFile($sFP & $sCriteria);         and checked with the criteria.
               While $iH2 <> - 1
                  $sCF2 = FileFindNextFile($iH2)
                  If @error Then
                     FileClose($iH2)
                     ExitLoop
                  EndIf
                  If $sCF2 = '.' Or $sCF2 = '..' Then ContinueLoop
                  $sOutPut = $sOutPut & $sFP & $sCF2 & @LF;Found items are put in the Output.
               Wend
            EndIf
         Wend
         $sBuffer = StringReplace($sBuffer, @CR & $sCS & @LF, '')
      Until $sBuffer = ''
   EndIf
   
   If $sOutPut = '' Then
      $aNull[0] = 0
      Return $aNull
   Else
      Return StringSplit(StringTrimRight($sOutPut, 1), @LF)
   EndIf
EndFunc  ;==>_FileSearch
Edited by ezzetabi

Share this post


Link to post
Share on other sites

Or just as JS said...

$sFileName = '';Full path here

If StringInStr(FileGetAttrib($sFileName), 'd') Then
   Do
      DirRemove($sFileName,1)
      Sleep(1);avoid overloading CPU
   Until Not FileExists($sFileName)
Else
   Do
      FileDelete($sFileName)
      Sleep(1)
   Until Not FileExists($sFileName)
EndIf

Share this post


Link to post
Share on other sites

I think to sleep properly without over loading CPU shouldnt it be atleast between 10-100? I dont know much I am not trying to correct I just want to know for my knowledge.

JS


AutoIt Links

File-String Hash Plugin Updated! 04-02-2008 Plugins have been discontinued. I just found out.

ComputerGetInfo UDF's Updated! 11-23-2006

External Links

Vortex Revolutions Engineer / Inventor (Web, Desktop, and Mobile Applications, Hardware Gizmos, Consulting, and more)

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Well, you know. Nowadays ours microprocessors may have 3 or 4 Ghertz of clock rate, it means that they can do 3 000 000 000 - 4 000 000 000 single clock operations per second. So just awaiting a 1/1000 of sec means allow them doing 3 000 000 - 4 000 000 operations becore taking some clocks again for tring to delete again. (It is not a CPU expensive procedure)

Of course there are no problems using a larger number if you prefere.

Edit: typo.

Edited by ezzetabi

Share this post


Link to post
Share on other sites

Well, finally some time to script again.

Or just as JS said...

$sFileName = '';Full path here

If StringInStr(FileGetAttrib($sFileName), 'd') Then
   Do
      DirRemove($sFileName,1)
      Sleep(1);avoid overloading CPU
   Until Not FileExists($sFileName)
Else
   Do
      FileDelete($sFileName)
      Sleep(1)
   Until Not FileExists($sFileName)
EndIf

<{POST_SNAPBACK}>

Looks fine to me, however the expression Until Not FileExists does not seem to work for me. Is there any expression that checks for the NON existence of files at all?

I've tried a different approach: I'm checking if there's any file in the dir left, if so, the script should wait for a second and then try again to delete the dir recursively. It looks like this but does not work since I do not get '-1' returned:

If $sourcedel = 1 And $reauthor = 0 Then
      $delfiles=$deldir & "\*.*"
      $search=FileFindFirstFile($delfiles)
      Do
         DirRemove($deldir, 1)
         Sleep(1000)
      Until $search = -1
      FileClose($search)
    EndIf

Any suggestions?


MultiMakeMKV: batch processing for MakeMKV (Win)MultiShrink: batch processing for DVD ShrinkOffizieller Übersetzer von DVD Shrink deutsch

Share this post


Link to post
Share on other sites

I've tried a different approach: I'm checking if there's any file in the dir left, if so, the script should wait for a second and then try again to delete the dir recursively. It looks like this but does not work since I do not get '-1' returned:

If $sourcedel = 1 And $reauthor = 0 Then
      $delfiles=$deldir & "\*.*"
      $search=FileFindFirstFile($delfiles)
      Do
         DirRemove($deldir, 1)
         Sleep(1000)
      Until $search = -1
      FileClose($search)
    EndIf

Any suggestions?

<{POST_SNAPBACK}>

Are there really files left in the folder, or is it because of how FileFindFirstFile works. When *.* is used with FileFindFirstFile, it always sees the "." and the ".." folders. This little tid-bit is hidden in the help file comment for the FileFindFirstFile example.

I believe it was yesterday that someone had a similar problem and someone suggested using the DirGetSize function which returns 0 when the folder is empty.


Phillip

Share this post


Link to post
Share on other sites

I believe it was yesterday that someone had a similar problem and someone suggested using the DirGetSize function which returns 0 when the folder is empty.

<{POST_SNAPBACK}>

I've tried DirGetSize like this

If $sourcedel = 1 And $reauthor = 0 Then
      $empty=DirGetSize($deldir)
      Do
         DirRemove($deldir,1)
         Sleep(1000)
      Until $empty=0
   EndIf

But it never works since the Until is never reached. What weirds me out is that I can use my Total Commander and delete the entire $deldir manually, so it's obviously not locked anymore. Still the Do-loop is never left except I change it to

Until $empty=8372224

which is exactly the size of the $deldir (my dummy DVD) to be deleted in bytes. I don't get it. Let me stress that again: the instance of DVD Shrink as well as the DVD openend from this instance are closed before the $deldir command is reached. I've got no idea why it's not working.


MultiMakeMKV: batch processing for MakeMKV (Win)MultiShrink: batch processing for DVD ShrinkOffizieller Übersetzer von DVD Shrink deutsch

Share this post


Link to post
Share on other sites

#12 ·  Posted (edited)

If $sourcedel = 1 And $reauthor = 0 Then
     $empty=DirGetSize($deldir)
     Do
        DirRemove($deldir,1)
        Sleep(1000)
     Until $empty=0
  EndIf

Don't understand the logic for the Do.. until... $Empty is never update inside this loop.

Why not just remove those 2 lines ?

Edited by JdeB

Visit the SciTE4AutoIt3 Download page for the latest versions        Beta files                                                          Forum Rules
 
Live for the present,
Dream of the future,
Learn from the past.
  :)

Share this post


Link to post
Share on other sites

#13 ·  Posted (edited)

I've tried DirGetSize like this

If $sourcedel = 1 And $reauthor = 0 Then
      $empty=DirGetSize($deldir)
      Do
         DirRemove($deldir,1)
         Sleep(1000)
      Until $empty=0
   EndIf

But it never works since the Until is never reached. What weirds me out is that I can use my Total Commander and delete the entire $deldir manually, so it's obviously not locked anymore. Still the Do-loop is never left except I change it to

Until $empty=8372224

which is exactly the size of the $deldir (my dummy DVD) to be deleted in bytes. I don't get it. Let me stress that again: the instance of DVD Shrink as well as the DVD openend from this instance are closed before the $deldir command is reached. I've got no idea why it's not working.

<{POST_SNAPBACK}>

What JdeB said, but to have you Do Until work, restructure it as follows:

If $sourcedel = 1 And $reauthor = 0 Then

Do

DirRemove($deldir,1)

Sleep(1000)

Until DirGetSize($deldir) = -1

EndIf

EDIT:

Oops. Changed value to -1 on the Until line because DirGetSize returns -1 when after the directory is deleted. Otherwise the loop will not exit.

Edited by phillip123adams

Phillip

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

What JdeB said, but to have you Do Until work, restructure it as follows:

Duh, seems I'm even less of a programmer than I thought. However, your version seems to work fine. I can't be 100% sure since the error wasn't reproduciable. I've ripped about 10 DVDs with this new method and all dirs were deleted just fine. Thanks.

Edited by Chetwood

MultiMakeMKV: batch processing for MakeMKV (Win)MultiShrink: batch processing for DVD ShrinkOffizieller Übersetzer von DVD Shrink deutsch

Share this post


Link to post
Share on other sites

Duh, seems I'm even less of a programmer than I thought. However, your version seems to work fine. I can't be 100% sure since the error wasn't reproduciable. I've ripped about 10 DVDs with this new method and all dirs were deleted just fine. Thanks.

<{POST_SNAPBACK}>

I've been trying to get DirRemove to fail, but it has always worked for me on the first pass. However, you could modify your loop, as shown below, and if a failure occurs it will record the information in a text file, break the loop after 10 iterations, and open the text file in NotePad. You can test the code if you prevent the directory from being deleted by opening one of its text files in NotePad before running the script.

; <<<< For testing only >>>>
$sFile = "c:\DirRemove-Did-Not-Remove-Itself.txt"
$Cnt = 0
; <<<< For testing only >>>>

If $sourcedel = 1 And $reauthor = 0 Then
   Do
      DirRemove($deldir,1)
      Sleep(1000)

; <<<< For testing only >>>>
$DirSize = DirGetSize($deldir)
If $DirSize <> -1 Then
   $Cnt = $Cnt + 1
   SplashTextOn("DirRemove not working", $Cnt & ".  Folder " & $deldir & " is " & $DirSize & " bytes on pass " & $Cnt & " at " & @Hour & ":" & @Min & ":" & @Sec, 400, 30)
   $hFile = FileOpen($sFile, 1); <<< adjust filename
   FileWriteLine($hFile, "Folder " & $deldir & " is " & $DirSize & " bytes on pass " & $Cnt & " at " & @Hour & ":" & @Min & ":" & @Sec)
   FileClose($hFile)
   Sleep(1000)
   SplashOff()
   If $Cnt = 10 Then ExitLoop
EndIf
; <<<< For testing only >>>>
     
   Until DirGetSize($deldir) = -1
EndIf

; <<<< For testing only >>>>
If $Cnt > 0 Then Run("NotePad.exe " & $sFile)
; <<<< For testing only >>>>

Phillip

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0