2026-06-29 20:43:05 -05:00 | | | //+------------------------------------------------------------------+
|
| | | //| Pw.mqh |
|
| | | //| Copyright 2026, Niquel Mendoza. |
|
| | | //| https://www.mql5.com/ |
|
| | | //+------------------------------------------------------------------+
|
| | | #property copyright "Copyright 2026, Niquel Mendoza."
|
| | | #property link "https://www.mql5.com/"
|
| | | #property strict
|
| | |
|
| | | #ifndef FULLMT5MCPBYLEO_SRC_COMPLEX_PW_MQH
|
| | | #define FULLMT5MCPBYLEO_SRC_COMPLEX_PW_MQH
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| Include |
|
| | | //+------------------------------------------------------------------+
|
| | | #include "..\\Def\\Def.mqh"
|
| | |
|
| | | //+------------------------------------------------------------------+
|
| | | //| |
|
| | | //+------------------------------------------------------------------+
|
| | | namespace TSN
|
| | | {
|
| | | class CMcpFuncRunCommand : public CMcpFunction
|
| | | {
|
| | | private:
|
| | | int m_mode;
|
| | |
|
| | | public:
|
| | | CMcpFuncRunCommand(int mode)
|
| | | : CMcpFunction(0, false, "run_command"), m_mode(mode) {}
|
| | | ~CMcpFuncRunCommand(void) {}
|
2026-07-13 21:11:54 -05:00 | | | void Run(CJsonNode& param, CJsonBuilderStr* &out) override final;
|
2026-06-29 20:43:05 -05:00 | | | };
|
| | |
|
| | | //+------------------------------------------------------------------+
|
2026-07-13 21:11:54 -05:00 | | | void CMcpFuncRunCommand::Run(CJsonNode& param, CJsonBuilderStr* &out)
|
2026-06-29 20:43:05 -05:00 | | | {
|
| | | //---
|
2026-07-13 21:11:54 -05:00 | | | out = m_shared_builder;
|
2026-06-30 10:46:22 -05:00 | | | const string command = param["run"].ToStringNoEscape("");
|
2026-06-29 20:43:05 -05:00 | | | const uint timeout = uint(param["timeout_segundos"].ToInt(1) * 1000);
|
| | | //---
|
| | | if(command == "")
|
| | | {
|
2026-07-13 21:11:54 -05:00 | | | m_shared_builder.PutChar('"');
|
| | | m_shared_builder.Obj();
|
| | | m_shared_builder.KeyWV("ok").Val(false);
|
| | | m_shared_builder.KeyWV("result").ValSWV("Empty command");
|
| | | m_shared_builder.EndObj();
|
| | | m_shared_builder.PutChar('"');
|
2026-06-29 20:43:05 -05:00 | | | return;
|
| | | }
|
| | | if(m_mode == 0)
|
| | | {
|
2026-07-13 21:11:54 -05:00 | | | m_shared_builder.PutChar('"');
|
| | | m_shared_builder.Obj();
|
| | | m_shared_builder.KeyWV("ok").Val(false);
|
| | | m_shared_builder.KeyWV("result").ValSWV("The user has disabled the use of this tool in the EA settings.");
|
| | | m_shared_builder.EndObj();
|
| | | m_shared_builder.PutChar('"');
|
2026-06-29 20:43:05 -05:00 | | | return;
|
| | | }
|
| | |
|
2026-06-30 10:46:22 -05:00 | | | //--- Nombre único de archivo temporal, relativo a la carpeta Files (para usarlo con funciones nativas MQL5)
|
| | | const string rel_file = "McpMt5ByLeo\\temp.txt";
|
| | |
|
| | | //--- Asegurar que la subcarpeta exista, en el ámbito Common
|
| | | FolderCreate("McpMt5ByLeo", FILE_COMMON);
|
| | |
|
| | | //--- Ruta absoluta real en disco: Common + \Files\ + subcarpeta + archivo
|
| | | const string abs_path = TERMINAL_MT5_COMMON_PATH + "\\Files\\" + rel_file;
|
| | |
|
| | | //--- Borrar cualquier residuo previo antes de ejecutar
|
| | | FileDelete(rel_file, FILE_COMMON);
|
| | |
|
| | | //--- El propio shell redirige su salida (stdout + stderr) al archivo
|
| | | string ps_args = "-NoProfile -NonInteractive";
|
2026-06-29 20:43:05 -05:00 | | | if(m_mode == 1)
|
2026-06-30 10:46:22 -05:00 | | | ps_args += " -ExecutionPolicy AllSigned";
|
| | | else
|
| | | if(m_mode == 2)
|
| | | ps_args += " -ExecutionPolicy Restricted";
|
2026-06-29 20:43:05 -05:00 | | |
|
2026-06-30 10:46:22 -05:00 | | | string ps_inner =
|
| | | "$out = & { " + command + " } 2>&1 | Out-String; " +
|
| | | "[System.IO.File]::WriteAllText('" + abs_path + "', $out, [System.Text.UTF8Encoding]::new($false))";
|
| | | string full_command = "powershell " + ps_args + " -Command \"" + ps_inner + "\"";
|
2026-06-29 20:43:05 -05:00 | | |
|
| | | //---
|
| | | PROCESS_INFORMATION pi;
|
| | | STARTUPINFOW si;
|
| | | ZeroMemory(pi);
|
| | | ZeroMemory(si);
|
| | | si.cb = sizeof(si);
|
2026-06-30 10:46:22 -05:00 | | | si.dwFlags = STARTF_USESHOWWINDOW;
|
| | | si.wShowWindow = SW_HIDE;
|
2026-06-29 20:43:05 -05:00 | | |
|
| | | //---
|
2026-06-30 10:46:22 -05:00 | | | const int created = CreateProcessW(NULL, full_command, NULL, NULL, 0, 0x08000000, NULL, NULL, si, pi);
|
2026-06-29 20:43:05 -05:00 | | |
|
| | | if(created == 0)
|
| | | {
|
2026-07-13 21:11:54 -05:00 | | | m_shared_builder.PutChar('"');
|
| | | m_shared_builder.Obj();
|
| | | m_shared_builder.KeyWV("ok").Val(false);
|
| | | m_shared_builder.KeyWV("result").ValSWV(StringFormat("Failed call CreateProcessW, last error = %u", GetLastError()));
|
| | | m_shared_builder.EndObj();
|
| | | m_shared_builder.PutChar('"');
|
2026-06-29 20:43:05 -05:00 | | | return;
|
| | | }
|
| | |
|
2026-06-30 10:46:22 -05:00 | | | //--- Esperar a que el proceso termine
|
2026-06-29 20:43:05 -05:00 | | | const uint wait_result = WaitForSingleObject(pi.hProcess, timeout);
|
| | | if(wait_result == WAIT_TIMEOUT_VAL)
|
| | | TerminateProcess(pi.hProcess, 1);
|
| | |
|
| | | uint exit_code = 0;
|
| | | GetExitCodeProcess(pi.hProcess, exit_code);
|
| | |
|
| | | CloseHandle(pi.hProcess);
|
| | | CloseHandle(pi.hThread);
|
| | |
|
2026-06-30 10:46:22 -05:00 | | | //--- Leer el contenido del archivo con funciones nativas de MQL5 (ámbito Common)
|
| | | uchar data[];
|
| | | const long size = FileLoad(rel_file, data, FILE_COMMON);
|
| | |
|
| | | //--- Borrar el archivo temporal para no acumular basura
|
| | | FileDelete(rel_file, FILE_COMMON);
|
| | |
|
2026-06-29 20:43:05 -05:00 | | | //---
|
2026-07-13 21:11:54 -05:00 | | | m_shared_builder.PutChar('"');
|
| | | m_shared_builder.Obj();
|
| | | m_shared_builder.KeyWV("ok").Val(bool(exit_code == 0));
|
| | | m_shared_builder.KeyWV("result").Obj();
|
| | | m_shared_builder.KeyWV("exit_code").Val(int(exit_code));
|
| | | m_shared_builder.KeyWV("stdout").ValU(data);
|
| | | m_shared_builder.EndObj();
|
| | | m_shared_builder.EndObj();
|
| | | m_shared_builder.PutChar('"');
|
2026-06-29 20:43:05 -05:00 | | | }
|
| | | }
|
| | | //+------------------------------------------------------------------+
|
| | | #endif // FULLMT5MCPBYLEO_SRC_COMPLEX_PW_MQH
|