A folder is not deleted if it contains unclosed files - page 8

 

I'll post a script reproducing the problem later.

If the problem is somehow solved, I'll explain everything in detail.

 
Реter Konow:

1. the handle is only needed for the FileClose function. I don't open the file. It was created before me. I just copy and delete it. I cannot close it because there is no handle.

2. File handle is not needed for copying (FileCopy), for moving (FileMove). Look at the documentation.

3. if I open a file created by someone else using FileOpen function, I will not get its handle. It is not known at all which handle I will get. It may be his or may be quite a different one. I tried to get the handle of someone else's file so I could close FileClose it after the copy operation. It didn't work.

4. When copying, the handle is not needed. It is copied without any problems. But the file is automatically opened for copying. Further, I can't close it with FileClose because there is no handle. This is probably why FolderClean does not work after erasing the copied files.

5. How do you know the file is not open after copying? It was not explicitly opened by the FileOpen function, but it was being copied with, which means it is open. Hence it remains open after copying and even after erasing. Probably.

A file handle is needed not only to close a file, but also to read and write to a file, manage a file pointer to read from a specified line or write to a specified line. Other functions that require a file handle can be found in the documentation.

2. I couldn't tell you that to copy or move a file you need a handle to that file? You misunderstood something.

If you open any file, no matter by whom or when created, you get its handle when FileOpen is executed.

I suspect you misunderstand what a handle is. Take 2 files for an experiment, you can have them ready, you can open them for writing and get their handles. They will differ by one. Then reverse the order of opening these files and you will see the same handles, but they will belong to different files. Second option: Open a file, get the handle = 1, close that file and open another one... and the handle of the other file will also be =1.

A handle is the numbering of the files inside the program and it has nothing to do with the contents of the file or its other attributes.

4. The file will not be opened during copying. And if you are copying by reading one file and writing the entire contents to another file, the handles of those files must be put in the appropriate variables for further manipulation of those files.

5. A file may take a few milliseconds during copying, exactly as long as it takes to save it to disk. From there it is as free as a bird in the sky... No chance of anything happening.

 

I'm happy to report that the problem is completely solved!)

The reason:

When building a copy of the file hierarchy in the array, in order to reproduce it in a usable file navigator, a special function was reading this hierarchy using FileFindFirst() and FileFindNext().

Initially, after each folder was scanned, the FileFindClose() function was called at the end of the loop to close the search handle for each specific folder.

Obviously, due to long and complex manipulations with the function that reads the file hierarchy, I accidentally erased this entry FileFindClose() and did not notice it. It didn't affect the performance of my navigator, until I started trying to rename folders. That's where the problem started.

The files, as it turned out, had nothing to do with it at all in this case. Of course, it's very helpful that I've learnt that they must be closed, even if no operations have been performed on them. In the future, it will keep me from making the same mistakes.


In general, the reason why my FolderClean() function didn't work was that long before I used it, during the initialization phase of the program, another function didn't close the FileFindFirst() search handles after scanning folders.

As it turned out, these things are related...


I made a script to reproduce the problem, but for some reason in this script, this problem is not reproduced. That is, in my program adding/removing line "FileFindClose(search_handle)" does affect the problem, but in the script, for some reason, it does not.

I am attaching the script below. Create a folder "1" in the Files folder and put any other folder or file there. When you load the script, the folder should be erased. If you comment out the line "FileFindClose(search_handle)", the script will still erase the folder, but in my program without this line folders are not erased. The reason is not clear.

//+------------------------------------------------------------------+
//|                                             Demo_FolderClean.mq4 |
//|                                                      Peter Konow |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Peter Konow"
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//Данный скрипт, сразу после загрузки должен стереть все содержимое 
//папки "1\\" внутри директории "Files".
//Однако, если хэндл поиска, открытый сразу после запуска скрипта функцией
//"FileFindFirst()" не закрыт, то скрипт не сможет стереть папку "1\\".

//Данный скрипт создан для демонстрации взаимосвязи закрытия хэндла поиска
//возвращаемого функцией "FileFindFirst()" и успешной работы функции "FolderClean()".
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   
   //---- Переменная необходимая для функции  "FileFindFirst()" 
   string file_name;
   //-----------------------------
   //Открываем поиск внутри папки "1\\".
   //-----------------------------
   long search_handle=FileFindFirst("1\\",file_name); 
   //--- проверим, успешно ли отработала функция FileFindFirst() 
   if(search_handle!=INVALID_HANDLE) 
     { 
      int i = 0;
      //--- в цикле проверим являются ли переданные строки именами файлов или директорий 
      do 
        { 
         ResetLastError(); 
         //--- если это файл, то функция вернет true, а если директория, то функция генерирует ошибку ERR_FILE_IS_DIRECTORY 
         FileIsExist(file_name); 
         PrintFormat("%d : %s name = %s",i,GetLastError()==ERR_FILE_IS_DIRECTORY ? "Directory" : "File",file_name); 
         i++; 
        } 
      while(FileFindNext(search_handle,file_name)); 
      //--- закрываем хэндл поиска 
      FileFindClose(search_handle); 
     } 
   else 
      Print("Files not found!");/**/ 
   //-----------------------------
   //Переходим к очищению папки "1\\" и ее последующему стиранию.
   //-----------------------------
   if(!FolderClean("1\\"))
   //--- Очищаем папку.
     Print("FolderClean  Error ",GetLastError());
   
   else 
     {//--- Стираем папку.
      if(!FolderDelete("1\\"))
        Print("FolderDelete  Error ",GetLastError());
      
      else 
       Print("Folder was cleaned and removed");
     } 
  }
//+------------------------------------------------------------------+