Вопросы от начинающих MQL5 MT5 MetaTrader 5 - страница 1548

 
Aleksandr Slavskii #:

Не заметил, что разговор про скрипт.

Если в скрипт, то так:

Не забудьте разрешить dll в настройках

Александр, добрый день!

Вы существенно мне помогли, посоветовав использовать kernel32.dll со следующей командой:

DeleteFile(TerminalInfoString(TERMINAL_DATA_PATH) + "\\Tester\\cache\\"); // Очистка Cache, чтобы гарантировать реальный прогон (а не воспроизведение данных запомненного ранее из opt-файла)

Теперь моя программа работает безукоризненно, спасибо вам большое!


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

В моем скрипте формируется набор оптимальных параметров Settings и записывается в песочницу Files с именем NameSettings, которое формируется в коде.

Вот пример сформированного имени: 701-2.3-15097.set.

Мне требуется записать его в папку тестера: C:\Users\клыков\AppData\Roaming\MetaQuotes\Terminal\F58594996208E46D021F1E606AD322F3\MQL5\Profiles\Tester

Я думаю, это можно сделать при помощи команды WriteFile() из kernel32.dll.

Но не понимаю, с какими параметрами ее записать.


#import "kernel32.dll"

int  DeleteFileW(const string file_name);

long FindFirstFileW(const string file_name, FIND_DATAWW &find_file_data);

int  FindNextFileW(long find_file, FIND_DATAWW &find_file_data);

int  FindClose(long find_file);

int WriteFile();

#import


Вот фрагмент кода моего скрипта:


   Now = TimeLocal();                         // Момент формирования имени для Settings (эта строка уже сформирована ранее)

   TimeToStruct(Now,dt_struct);               // Разложение момента формирования

   string mnth = dt_struct.mon;               // Месяц, день

   int dyy = dt_struct.day;

   string dy = dt_struct.day;

   if(dyy <= 9)

      dy = "0" + dy;

   string LimPos = MTTESTER::GetValue(Settings,"LimitPosition");                    // LimitPosition считывается

   int PosVert = StringFind(LimPos,"|",0);

   string razn = StringSubstr(LimPos,PosVert,-1);

   StringReplace(LimPos,razn,"");

   NameSettings = mnth+dy+"-"+LimPos+"-"+DoubleToString(ProfitNew,0)+".set";      // Формируется имя для Settings

   int file_handle=FileOpen("//"+NameSettings,FILE_READ|FILE_WRITE|FILE_CSV|FILE_ANSI);

   FileWriteString(file_handle,Settings+"\r\n");                                    // Записывается строка Settings в песочницу Files


Вот здесь и хотелось бы добавить эту команду записи в папку Tester.


Помогите, пожалуйста!


С уважением, Александр


 
klycko #:

Александр, добрый день!

Вот выдрал у себя из кода как копировать файл из папки в папку.

Я не помню, что я копировал и куда, но мне кажется это то, что вам нужно)))

Попробуйте разобраться. 

#define MAX_PATH                       260

struct FILETIME
  {
   uint              dwLowDateTime;
   uint              dwHighDateTime;
  };
struct FIND_DATAW
  {
   uint              dwFileAttributes;
   FILETIME          ftCreationTime;
   FILETIME          ftLastAccessTime;
   FILETIME          ftLastWriteTime;
   uint              nFileSizeHigh;
   uint              nFileSizeLow;
   uint              dwReserved0;
   uint              dwReserved1;
   short             cFileName[MAX_PATH];
   short             cAlternateFileName[14];
  };

#import "user32.dll"
bool CopyFileW(string lpExistingFileName, string lpNewFileName, bool bFailIfExists);
long FindFirstFileW(const string file_name, FIND_DATAW &find_file_data);
int  FindNextFileW(long find_file, FIND_DATAW &find_file_data);
int  FindClose(long find_file);
#import
//+------------------------------------------------------------------+
bool IsCopi(string Name)
  {
//---находим файл с фреймами
   string FileName = "";
   string FileNameTemp = "";
   int count = 0;
   long search_handle = FileFindFirst("Tester\\*.mqd", FileNameTemp);
   do
     {
      if(FileNameTemp != "")
         count++;
      if(count > 1)
        {
         if(FileGetInteger("Tester\\" + FileNameTemp, FILE_CREATE_DATE, false) > FileGetInteger("Tester\\" + FileName, FILE_CREATE_DATE, false))
            FileName = FileNameTemp;
        }
      else
         FileName = FileNameTemp;
     }
   while(FileFindNext(search_handle, FileNameTemp));
   FileFindClose(search_handle);

   FileCopy("Tester\\" + FileName, 0, "ResOpt\\" + Name + "\\" + FileName, FILE_REWRITE);
//---
   string PathName = TerminalInfoString(TERMINAL_DATA_PATH);
   string Path = PathName + "\\Tester\\cache\\";
   string File = GetFileName(Path);
   string FileNew = PathName + "\\MQL5\\Files\\ResOpt\\" + Name + "\\" + File;

   int aaa = CopyFileW(Path + File, PathName + "\\MQL5\\Files\\ResOpt\\" + File, false);
   Sleep(300);
   FileCopy("ResOpt\\" + File, 0, "ResOpt\\" + Name + "\\" + File, FILE_REWRITE);
   FileDelete("ResOpt\\" + File);

   return true;
  }
//+------------------------------------------------------------------+
// Получает имя файла оптимизации
string GetFileName(string Path)
  {
   FIND_DATAW FindData;
   FindData.cFileName[0] = 0;
   const long handle = FindFirstFileW(Path + "*.opt*", FindData);
   string FileName = "";
   if(handle != INVALID_HANDLE)
     {
      do
        {
         FileName = ShortArrayToString(FindData.cFileName);
        }
      while(FindNextFileW(handle, FindData));

      FindClose(handle);
     }

   return(FileName);
  }
//+------------------------------------------------------------------+


Ага, вспомнил чуть. Код избыточен для вас. Он копирует файл оптимизации из папки тестер в куда то. Причём выбирает самый последний(свежий) файл. Вот эта оценка свежести, думаю вам не нужна)

ЗЫЫ  всё что вам из всего этого надо это CopyFileW,всё остальное вода)))

 

Добавил такие команды:

   string PathName = TerminalInfoString(TERMINAL_DATA_PATH);

   string Path = PathName + "\\Files\\";

   string FileNew = PathName + "\\MQL5\\Profiles\\Tester\\" + NameSettings + "\\";


   Print("PathName= ",PathName);

   Print("Path= ",Path);

   Print("FileNew= ",FileNew);


   bool aaa = CopyFileW(Path + NameSettings, FileNew, false);

   PrintFormat("Error %d",GetLastError()); // информация о неудачной операции

   Print("aaa= ",aaa);


В результате получил:

PathName= C:\Users\клыков\AppData\Roaming\MetaQuotes\Terminal\F58594996208E46D021F1E606AD322F3

Path= C:\Users\клыков\AppData\Roaming\MetaQuotes\Terminal\F58594996208E46D021F1E606AD322F3\Files\

FileNew= C:\Users\клыков\AppData\Roaming\MetaQuotes\Terminal\F58594996208E46D021F1E606AD322F3\MQL5\Profiles\Tester\702-2.3-15097.set\

Error 4009

aaa= false

ERR_NOTINITIALIZED_STRING

4009

Неинициализированная строка


Вроде все пути определены правильно, но копирования не происходит.

Сама процедура импортируется из:

#import "kernel32.dll"

int  DeleteFileW(const string file_name);

long FindFirstFileW(const string file_name, FIND_DATAWW &find_file_data);

int  FindNextFileW(long find_file, FIND_DATAWW &find_file_data);

int  FindClose(long find_file);

bool CopyFileW(string lpExistingFileName, string lpNewFileName, bool bFailIfExists);

//int WriteFile();

#import

 
klycko #:

Добавил такие команды:

Хз.

Ну для начала я бы убрал слэш в конце этой строки

FileNew= C:\Users\клыков\AppData\Roaming\MetaQuotes\Terminal\F58594996208E46D021F1E606AD322F3\MQL5\Profiles\Tester\702-2.3-15097.set\

вот так

string FileNew = PathName + "\\MQL5\\Profiles\\Tester\\" + NameSettings;
 

Не помогло.

Та же самая ошибка 4009.


Попробовал просто переписать файл внутри песочницы. Ошибка та же.

   string PathName = TerminalInfoString(TERMINAL_DATA_PATH);

   string Path = PathName + "\\Files\\";

//   string FileNew = PathName + "\\MQL5\\Profiles\\Tester\\" + NameSettings;

   string FileNew = PathName + "\\MQL5\\Files\\" + "f"+NameSettings;

   Print("PathName= ",PathName);

   Print("Path= ",Path);

   Print("FileNew= ",FileNew);


   bool aaa = kernel32::CopyFileW(Path + NameSettings, FileNew, false);

   PrintFormat("Error %d",GetLastError()); // информация о неудачной операции

   Print("aaa= ",aaa);


А результат такой:

PathName= C:\Users\lizak\AppData\Roaming\MetaQuotes\Terminal\FA97EA291D4188820508F9D2B5AAD50F

Path= C:\Users\lizak\AppData\Roaming\MetaQuotes\Terminal\FA97EA291D4188820508F9D2B5AAD50F\Files\

FileNew= C:\Users\lizak\AppData\Roaming\MetaQuotes\Terminal\FA97EA291D4188820508F9D2B5AAD50F\MQL5\Files\f702-2.3-15097.set

Error 4009

aaa= false


 
klycko #:

Не помогло.

Создал в папке  C:\Users\Ya\AppData\Roaming\MetaQuotes\Terminal\FA97EA291D4188820508F9D2B5AAD50F\MQL5\Files  файл  с таким именем File.csv

Запускаю скрипт.

Файл как и задуманно копируется в папку   C:\Users\Ya\AppData\Roaming\MetaQuotes\Terminal\FA97EA291D4188820508F9D2B5AAD50F

Всё работает.

#import "kernel32.dll"
bool CopyFileW(string lpExistingFileName, string lpNewFileName, bool bFailIfExists);
#import
//+------------------------------------------------------------------+
void OnStart()
  {
   string File = "File.csv";
   string Path = TerminalInfoString(TERMINAL_DATA_PATH);
   string LastPath = Path + "\\MQL5\\Files\\" + File;  
   string NewPath = Path + "\\" + File;                
   bool res = kernel32::CopyFileW(LastPath, NewPath, false);
   Print(res);
  }
//+------------------------------------------------------------------+
 
klycko #:

Кстати.

123589

 
Aleksandr Slavskii #:

Создал в папке  C:\Users\Ya\AppData\Roaming\MetaQuotes\Terminal\FA97EA291D4188820508F9D2B5AAD50F\MQL5\Files  файл  с таким именем File.csv

Запускаю скрипт.

Файл как и задумано копируется в папку   C:\Users\Ya\AppData\Roaming\MetaQuotes\Terminal\FA97EA291D4188820508F9D2B5AAD50F

Всё работает.

К сожалению, ваш код у меня не сработал. 

Тогда я еще более упростил задачу: переписать файл внутри песочницы, но с новым именем:

//+------------------------------------------------------------------+
//|                                                        proba.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

#import "kernel32.dll"
bool CopyFileW(string lpExistingFileName, string lpNewFileName, bool bFailIfExists);
#import
//+------------------------------------------------------------------+
void OnStart()
  {
   string File = "File.csv"; 
   string Path = TerminalInfoString(TERMINAL_DATA_PATH);
   string LastPath = Path + "\\MQL5\\Files\\" + File;
   string NewPath = Path + "\\MQL5\\Files\\" + "New_" + File;
//   string NewPath = Path + "\\" + File;
   Print("\nPath = ",Path);
   Print("LastPath = ",LastPath);
   Print("NewPath = ",NewPath);

   ResetLastError();
   bool res = kernel32::CopyFileW(LastPath, NewPath, false);
   PrintFormat("Error %d",GetLastError());                          // информация о неудачной операции
   Print("res = ",res);
  }
//+------------------------------------------------------------------+

Вот, что он распечатал:

Path = C:\Users\клыков\AppData\Roaming\MetaQuotes\Terminal\F58594996208E46D021F1E606AD322F3

LastPath = C:\Users\клыков\AppData\Roaming\MetaQuotes\Terminal\F58594996208E46D021F1E606AD322F3\MQL5\Files\File.csv

NewPath = C:\Users\клыков\AppData\Roaming\MetaQuotes\Terminal\F58594996208E46D021F1E606AD322F3\MQL5\Files\New_File.csv

Error 0

res = false


Нового файла в папке Files не появилось.

Удивительно, что Error 0 (т.е. ошибки нет), но res = false


Проверял на двух компьютерах, результат одинаковый.


Интересно, сработает ли этот код у вас?


У меня dll разрешены.

Но все же дело, наверное, в каких-то ещё настройках?

 
klycko #:

К сожалению, ваш код у меня не сработал. 

Я не знаю чем вам помочь.

Проверил ещё раз, всё работает.

#import "kernel32.dll"
bool CopyFileW(string lpExistingFileName, string lpNewFileName, bool bFailIfExists);
#import
//+------------------------------------------------------------------+
void OnStart()// создал файл File.csv в папке Files, скрипт копирует его в папку терминала
  {
   string File = "File.csv";
   string Path = TerminalInfoString(TERMINAL_DATA_PATH);
   string LastPath = Path + "\\MQL5\\Files\\" + File;
   string NewPath = "";

   for(int i = 0; i < 3; i++)
     {
      if(i == 0)
         NewPath = Path + "\\" + File;
      else
         if(i == 1)
            NewPath = LastPath + ".txt";
         else
            NewPath = Path + "\\New" + File;

      bool res = kernel32::CopyFileW(LastPath, NewPath, false);
      Print(res);
     }
  }
//+------------------------------------------------------------------+


Как вы можете видеть копирует хоть куда и с разными именами и даже со сменой расширения. 


PS  Проверьте на наличие файла, может вы где то, что то путаете.

вставьте в начало скрипта

   if(!FileIsExist("File.csv"))
      Print("Пошёл на хе..., нет в папке такого файла!");
 
Aleksandr Slavskii #:

Я не знаю чем вам помочь.

Проверил ещё раз, всё работает.


Как вы можете видеть копирует хоть куда и с разными именами и даже со сменой расширения. 


PS  Проверьте на наличие файла, может вы где то, что то путаете.

вставьте в начало скрипта

Спасибо за юмор!

Вечером проверю