Не удаляется папка, если в ней есть незакрытые файлы - страница 8

 

Чуть позже выставлю скрипт воспроизводящий проблему.

Если проблема как нибудь решиться, все подробно изложу.

 
Реter Konow:

1. Хендл нужен только для функции FileClose. Я файл не открываю. Он был создан до меня. Я его только копирую и стираю. Закрыть не могу, потому что нет хендла.

2. Для копирования (FileCopy), для перемещения (FileMove) хендл файла не нужен. Посмотрите в документации.

3. Если я открываю созданный кем то ранее файл функцией FileOpen, то я не получу его хендл. Неизвестно вообще, какой хендл я получу. Может быть его, а может совсем другой. Я пробывал так получать хендл чужого файла, чтобы после операции копирования его закрыть FileClose. Ничего не дало.

4. При копировании хэндл не нужен. Копируется без проблем. Но для копирования файл автоматически открывается. Далее, закрыть его с FileClose с не могу, потому что нет хендла. Вероятно поэтому не срабатывает FolderClean после стирания скопированных файлов.

5. Откуда Вы знаете, что после копирования файл не открыт? Он не был явно открыт функцией FileOpen, но с ним производилось копирование, а значит он открыт. Следовательно, он остается открыт после копирования и даже после стирания. Вероятно.

1. Хендл файла нужен не только для закрытия его, но так-же для чтения и записи в файл, управления файловым указателем с целью чтения с указанной строки или записи в указанную строку. Остальные функции требующие хендл файла можно посмотреть в документации.

2. Я и не мог сказать, что для копирования или перемещения файла нужен хендл этого файла? Вы что-то не так поняли.

3. Если Вы открываете любой файл, не важно кем и когда созданный, Вы получаете его хендл во время выполнения FileOpen.

Я подозреваю, что Вы неправильно понимаете что такое хендл. Возьмите для эксперимента 2 файла, можно готовых, можно открывать для записи и получите их хендлы. Они будут отличаться на единицу. Потом поменяйте очерёдность открытия этих файлов, Вы увидете те-же самые хендлы, но принадлежать они будут другим файлам. Второй вариант: Открываете файл, получаете хендл =1, закрываете этот файл и открываете другой... и хендл этого другого файла будет так-же =1.

Хендл это нумерация файлов исключительно внутри программы и никак не связан ни с содержимым файла, или прочими его атрибутами.

4. Во время копирования файл не открывается. А если Вы копируете чтением одного файла и записью всего содержимого в другой файл, то и хендлы этих файлов должны быть засунуты в соответствующие переменные для дальнейшей работы с этими файлами.

5. Во время копирования файл может быть занять несколько миллисекунд, ровно столько сколько требуется на сохранение его на диск. Дальше он свободен как птица в небе... Безо всяких вероятностей.

 

С радостью сообщаю, что проблема полностью разрешилась!)

Причина:

При построении копии файловой иерархии в массиве, для ее воспроизведения в польз. файловом навигаторе, специальная функция считывала эту иерархию с помощью функций FileFindFirst() и FileFindNext().

Изначально, после завершения сканирования каждой папки, в конце цикла вызывалась функция FileFindClose(), которая закрывала хэндл поиска каждой конкретной папки.

Очевидно, в следствии долгих и сложных манипуляций с функцией считывающий файловую иерархию, я случайно стер эту запись FileFindClose() и незаметил этого. На работу моего навигатора это не влияло, до тех пор, пока я не начал пытаться переименовывать папки. С этого и началась проблема.

Файлы, как оказалось, вообще не причем в данном случае. Конечно, очень полезно, что я узнал о необходимости их обязательного закрытия, даже если не с ними не производились операции. В будущем, это убережет меня от подобных ошибок.


В общем, причина того, что у меня не срабатывала функция FolderClean() была в том, что задолго до ее использования, еще на этапе инициализации программы, другая функция не закрыла хэндлы поиска функции FileFindFirst() после сканирования папок.

Как оказалось, эти вещи взаимосвязаны...


Я сделал скрипт для воспроизведения проблемы, но почему то в этом скрипте, эта проблема не воспроизводится. То есть, у меня в программе добавление/удаления строки "FileFindClose(search_handle)" действительно влияет на проблему, но в скрипте, почему то нет.

Ниже прилагаю скрипт. Создайте в папке Files папку "1" и поместите туда любую другую папку или файл. При загрузке скрипта, папка должна стереться.  Если закомментируете строку "FileFindClose(search_handle)", то скрипт все равно будет стирать папку, однако, в моей программе, без этой строки папки не стираются. Причина не ясна.

//+------------------------------------------------------------------+
//|                                             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");
     } 
  }
//+------------------------------------------------------------------+
Причина обращения: