Un dossier n'est pas supprimé s'il contient des fichiers non fermés. - page 8

 

Je posterai un script reproduisant le problème plus tard.

Si le problème est résolu d'une manière ou d'une autre, je vous expliquerai tout en détail.

 
Реter Konow:

1. la poignée n'est nécessaire que pour la fonction FileClose. Je n'ouvre pas le fichier. Il a été créé avant moi. Je le copie et le supprime. Je ne peux pas le fermer car il n'y a pas de poignée.

2. La poignée du fichier n'est pas nécessaire pour la copie (FileCopy), pour le déplacement (FileMove). Regardez la documentation.

3. si j'ouvre un fichier créé par quelqu'un d'autre en utilisant la fonction FileOpen, je n'obtiendrai pas son identifiant. On ne sait pas du tout quelle poignée je vais recevoir. Il peut s'agir du sien ou d'un tout autre. J'ai essayé d'obtenir le handle du fichier de quelqu'un d'autre pour pouvoir le fermer FileClose après l'opération de copie. Ça n'a pas marché.

4. Lors de la copie, la poignée n'est pas nécessaire. Il est copié sans aucun problème. Mais le fichier est automatiquement ouvert pour être copié. De plus, je ne peux pas le fermer avec FileClose car il n'y a pas de poignée. C'est probablement la raison pour laquelle FolderClean ne fonctionne pas après avoir effacé les fichiers copiés.

5. Comment savez-vous que le fichier n'est pas ouvert après la copie ? Il n'a pas été explicitement ouvert par la fonction FileOpen, mais il a été copié avec, ce qui signifie qu'il est ouvert. Il reste donc ouvert après la copie et même après l'effacement. Probablement.

Un handle de fichier est nécessaire non seulement pour fermer un fichier, mais aussi pour lire et écrire dans un fichier, gérer un pointeur de fichier pour lire à partir d'une ligne spécifiée ou écrire sur une ligne spécifiée. D'autres fonctions qui nécessitent un handle de fichier peuvent être trouvées dans la documentation.

2. Je n'ai pas pu vous dire que pour copier ou déplacer un fichier, il faut un identifiant pour ce fichier ? Vous avez mal compris quelque chose.

Si vous ouvrez un fichier, peu importe par qui ou quand il a été créé, vous obtenez son identifiant lorsque FileOpen est exécuté.

Je pense que vous ne comprenez pas ce qu'est une poignée. Prenez 2 fichiers pour une expérience, vous pouvez les avoir prêts, vous pouvez les ouvrir pour écrire et obtenir leurs poignées. Ils seront différents les uns des autres. Inversez ensuite l'ordre d'ouverture de ces fichiers et vous verrez les mêmes poignées, mais elles appartiendront à des fichiers différents. Deuxième option : Ouvrir un fichier, obtenir handle = 1, fermer ce fichier et en ouvrir un autre... et le handle de l'autre fichier sera également =1.

Un handle est la numérotation des fichiers à l'intérieur du programme et il n'a rien à voir avec le contenu du fichier ou ses autres attributs.

4. Le fichier ne sera pas ouvert pendant la copie. Et si vous copiez en lisant un fichier et en écrivant tout le contenu dans un autre fichier, les handles de ces fichiers doivent être placés dans les variables appropriées pour une manipulation ultérieure de ces fichiers.

5. La copie d'un fichier peut prendre quelques millisecondes, exactement le temps qu'il faut pour l'enregistrer sur le disque. De là, il est aussi libre qu'un oiseau dans le ciel... Aucune chance que quelque chose arrive.

 

Je suis heureux d'annoncer que le problème est complètement résolu).

La raison :

Lors de la construction d'une copie de la hiérarchie des fichiers dans le tableau, afin de la reproduire dans un navigateur de fichiers utilisable, une fonction spéciale lisait cette hiérarchie en utilisant FileFindFirst() et FileFindNext().

Initialement, après l'analyse de chaque dossier, la fonction FileFindClose() était appelée à la fin de la boucle pour fermer la poignée de recherche pour chaque dossier spécifique.

Évidemment, en raison de manipulations longues et complexes avec la fonction qui lit la hiérarchie des fichiers, j'ai accidentellement effacé cette entrée FileFindClose() et ne l'ai pas remarqué. Cela n'a pas affecté les performances de mon navigateur, jusqu'à ce que je commence à essayer de renommer des dossiers. C'est là que le problème a commencé.

Il s'est avéré que les dossiers n'avaient rien à voir dans cette affaire. Bien sûr, il est très utile que j'aie appris qu'il faut les fermer, même si je n'y ai rien fait. À l'avenir, cela m'évitera de faire les mêmes erreurs.


En général, la raison pour laquelle ma fonction FolderClean() n'a pas fonctionné est que bien avant que je ne l'utilise, pendant la phase d'initialisation du programme, une autre fonction n'a pas réussi à fermer les poignées de recherche FileFindFirst() après avoir analysé les dossiers.

Il s'est avéré que ces choses sont liées...


J'ai créé un script pour reproduire le problème, mais pour une raison quelconque dans ce script, ce problème n'est pas reproduit. En d'autres termes, dans mon programme, l'ajout/la suppression de la ligne "FileFindClose(search_handle)" a une incidence sur le problème, mais dans le script, pour une raison quelconque, ce n'est pas le cas.

Je joins le script ci-dessous. Créez un dossier "1" dans le dossier Files et placez-y tout autre dossier ou fichier. Si vous commentez la ligne "FileFindClose(search_handle)", le script effacera toujours le dossier, mais dans mon programme, sans cette ligne, les dossiers ne sont pas effacés. La raison n'est pas claire.

//+------------------------------------------------------------------+
//|                                             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");
     } 
  }
//+------------------------------------------------------------------+
Raison: