閉じていないファイルがある場合、フォルダは削除されない - ページ 2

 
Rashid Umarov:

何らかの理由で、オペレーティングシステムがファイルの削除を 許可しない - 別のプログラムによって開かれているか、十分な権限がないかのいずれかです。

まさにこの通り。すでにサブフォルダーやファイルを含むフォルダーを削除しようとすると、先にファイルを削除してしまう。サブフォルダーだけが残ります。FolderClean()でクリーニングしてから、FolderDelete()を呼び出すようにしています。しかし、その結果、空だったサブフォルダーはしっかり削除されますが、サブフォルダーの中にさらにサブフォルダーがあった場合は削除されないのです。その後、手動でMetaEditorのファイルナビゲータからフォルダを削除しようとするのですが、ターミナルでは削除されず、このようなウィンドウがポップアップ表示されます。

続行」をクリックし、変更に同意しましたが、フォルダはまだ消去されません。ターミナルを完全に閉じて開き直すと、消したはずのフォルダが勝手に消えたり消えなかったりしますが、上記のウィンドウがなくても、すぐに手動で消すことができます。

そんな奇想天外な...。

 
Vladimir Karputov:

古い端末ではMQL5のプログラムを見ることができないことを証明する必要があったのです。MQL5スクリプトで 他人のファイルサンドボックスを開こうとしている。

両端末とも機能は同じです。スクリプトを実行している端末のファイルサンドボックスが使用されます。使用する端末のネイティブファイルです。これは絶対に問題ないと信じて...。
 
Rashid Umarov:


PS そして、一般的に - プログラムログを与えないことは、他の人がコーヒーのかすで推測することを強制することです。

このGIFを見てください。



このスクリプトのコードは、上の前ページで紹介しました。

 

最初にソフトウェアで、次に手動で消そうとしているフォルダは、どこにも開いていないことを付け加えておきます。また、MetaEditorのファイルナビゲータ以外では開くことができません。なぜなら、それらは空であり、それらのファイルは以前に消去されているからです。消去されたファイルも、どこにも開かれていない。

MetaEditorのファイルナビゲータでフォルダを手動で消去する場合、FolderClean()やFolderDelete()で消去したフォルダを消去しようとすると、管理者の承認が必要なウィンドウが表示されます。他のフォルダーを削除しようとすると、このウィンドウは表示されません。

 
Реter Konow:

このスクリプトのFolderClean()関数が失敗するのはなぜですか?

フォルダーをクリーニングしようとすると、エラー5026 - (フォルダーをクリーニングできません)が発生します。

このスクリプトは、ドキュメント(FolderDelete()関数の セクション)から引用し、若干の修正を加えています。他のサブフォルダーやファイルを含むフォルダーを完全に削除するには、そのフォルダーを消去する必要があります。そのためにFolderClean()の呼び出しが追加されています。

ファイルのクローズアップがない理由を教えてください。それとも私が見ていないだけなのでしょうか?

ファイルを開いてから削除を要求するまでのコードの一部を紹介します。

   handle=FileOpen(filepath,FILE_WRITE|FILE_TXT); // флаг FILE_WRITE в данном случае обязателен, см. справку к функции FileOpen 
   if(handle!=INVALID_HANDLE) 
      PrintFormat("Открыли файл на чтение %s",working_folder+"\\"+filepath); 
   else 
      PrintFormat("Не удалось создать файл %s в папке %s. Код ошибки=",filename,secondFolder, GetLastError());
 
   Comment(StringFormat("Готовимся удалить папки %s и %s", firstFolder, secondFolder)); 
//--- Небольшая пауза в 5 секунд, чтобы мы могли прочитать сообщение на графике 
   Sleep(5000); // Sleep() нельзя использовать в индикаторах!
 
//--- выведем диалоговое окно и просим пользователя 
 
Alexey Viktorov:

ファイルを閉じることができない理由を教えてください。それとも私が見ていないだけなのでしょうか?

以下は、ファイルを開くところから削除に関する質問までのコードの断片です...

私の知る限り、ファイル関数(FileWrite()など)を使ってファイルに変更が加えられていない場合は、ファイルを閉じる必要はないようです。FileOpen()関数は単に新しいファイルを作成するだけで、この操作ではファイルを閉じる必要はありません(この関数のドキュメントも、作成後にファイルを閉じるべきとは書いていません)。なお、このスクリプトはドキュメントから引用しており、そこは何も変えていない。FolderClean()関数を 使った行を追加しただけです。
 
Реter Konow:
私の知る限り、FileWrite()を使用してファイルに変更が加えられていない場合、ファイルを閉じる必要はありません。FileOpen()関数は、単に新しいファイルを作成するもので、この操作ではファイルを閉じる必要はない。なお、このスクリプトはドキュメントから引用しており、そこは何も変えていない。FolderClean()関数を 使った行を追加しただけです。

しかし、デバッガを使ってコードを見てみると、FileOpen()が実行された直後に、ディスク上にNULLサイズのファイルが存在することがわかると思います。そして、ドキュメントにはむしろ多くの誤りや不正確な点があるのです。

 
Alexey Viktorov:

しかし、デバッガでコードを確認すると、FileOpen()が実行された直後にディスク上にゼロサイズのファイルが存在するのです。そして、ドキュメントにはむしろ多くの誤りや不正確な点があるのです。

ですから、この例では0サイズであるべきです。

今度は、スクリプトで明示的にファイルを閉じてみて、もう一度試してみます。

 
Реter Konow:

ですから、この例では0サイズであるべきです。

スクリプトで明示的にファイルを閉じる ようにして、もう一度試してみます。

サンプルコードを見ることはほとんどないので、問題なくフォルダを削除しています。だから、99%間違いなくそれが問題なのです。
 

結果は同じです。

以下は新しいコードです。

//+------------------------------------------------------------------+ 
//|                                            Demo_FolderDelete.mq5 | 
//|                        Copyright 2011, MetaQuotes Software Corp. | 
//|                                              https://www.mql5.com | 
//+------------------------------------------------------------------+ 
#property copyright "Copyright 2011, MetaQuotes Software Corp." 
#property link      "https://www.mql5.com" 
#property version   "1.00" 
//--- описание 
#property description "Скрипт показывает пример использования FolderDelete()." 
#property description "Сначала создаются две папки, одна пустая, другая содержит файл." 
#property description "При попытке удаления непустой папки получим ошибку и предупреждение."
 
//--- покажем окно входных параметров при запуске скрипта 
#property script_show_inputs 
//--- входные параметры 
input string   firstFolder="empty";    // пустая папка 
input string   secondFolder="nonempty";// папка, в которой будет один файл 
string filename="delete_me.txt";       // имя файла, который мы создадим в папке secondFolder 
//+------------------------------------------------------------------+ 
//| Script program start function                                    | 
//+------------------------------------------------------------------+ 
void OnStart() 
  { 
//--- хендл файла запишем сюда 
   int handle; 
//--- выясним в какой папке мы работаем 
   string working_folder=TerminalInfoString(TERMINAL_DATA_PATH)+"\\MQL4\\Files"; 
//--- отладочное сообщение    
   PrintFormat("working_folder=%s",working_folder); 
//--- попытка создать пустую папку относительно пути MQL4\Files 
   if(FolderCreate(firstFolder,0)) // 0 означает, что работаем в локальной папке терминала 
     { 
      //--- выведем полный путь до созданной папки 
      PrintFormat("Cоздали папку %s",working_folder+"\\"+firstFolder); 
      //--- сбросим код ошибки 
      ResetLastError(); 
     } 
   else 
      PrintFormat("Не удалось создать папку %s. Код ошибки %d",working_folder+"\\"+firstFolder, GetLastError());
 
//--- теперь создадим непустую папку с помощью функции FileOpen() 
   string filepath=secondFolder+"\\"+filename;  // сформируем путь для файла, который хотим открыть на запись в несуществующей папке 
   handle=FileOpen(filepath,FILE_WRITE|FILE_TXT); // флаг FILE_WRITE в данном случае обязателен, см. справку к функции FileOpen 
   if(handle!=INVALID_HANDLE) 
     {
//*************************************************************************     
   //---- Явно закрываем файл.   
      FileClose(handle);
//*************************************************************************           
      PrintFormat("Открыли файл на чтение %s",working_folder+"\\"+filepath); 
     } 
   else 
      PrintFormat("Не удалось создать файл %s в папке %s. Код ошибки=",filename,secondFolder, GetLastError());
 
   Comment(StringFormat("Готовимся удалить папки %s и %s", firstFolder, secondFolder)); 
//--- Небольшая пауза в 5 секунд, чтобы мы могли прочитать сообщение на графике 
   Sleep(5000); // Sleep() нельзя использовать в индикаторах!
 
//--- выведем диалоговое окно и просим пользователя 
   int choice=MessageBox(StringFormat("Удалить папки %s и %s?", firstFolder, secondFolder), 
                         "Удаление папок", 
                         MB_YESNO|MB_ICONQUESTION); //  будут две кнопки - "Yes" и "No"
 
//--- выполним действия в зависимости от выбранного варианта 
   if(choice==IDYES) 
     { 
      //--- очистим комментарий на графике 
      Comment(""); 
      //--- выведем сообщение в журнал "Эксперты" 
      PrintFormat("Пробуем удалить папки %s и %s",firstFolder, secondFolder); 
      ResetLastError(); 
      //--- удаляем пустую папку 
      if(FolderDelete(firstFolder)) 
         //--- должны увидеть это сообщение, так как папка пустая 
         PrintFormat("Папка %s успешно удалена",firstFolder); 
      else 
         PrintFormat("Не удалось удалить папку %s. Код ошибки=%d", firstFolder, GetLastError());
 
      ResetLastError(); 

   //***********************************************************************************************************************   
      //--- сначала очищаем папку
      if(FolderClean(secondFolder))
         PrintFormat("Папка %s успешно очищена", secondFolder);
      else 
         //---  
         PrintFormat("Не удалось очистить папку %s. Код ошибки=%d", secondFolder, GetLastError());
   //***********************************************************************************************************************   
   
      ResetLastError(); 
        
      //--- удаляем папку, которая содержит файл               
      if(FolderDelete(secondFolder)) 
         PrintFormat("Папка %s успешно удалена", secondFolder); 
      else 
         //--- 
         PrintFormat("Не удалось удалить папку %s. Код ошибки=%d", secondFolder, GetLastError()); 
     }  

   else 
      Print("Удаление отменено"); 
//--- 
  }