How to stop a running .exe file from MQL5 code?

 

Hi

I am building an Experts Advisor for MT5.

When it is attached to a chart, it successfully opens a .exe file.

However, when I remove my EA from the chart, the .exe is still running.

I tried a few functions available on internet, but I am unable to stop that running .exe


My code section initially was:

#import "shell32.dll"
   int ShellExecuteW(int hWnd, string Verb, string File, string Parameter, string Path, int ShowCommand);
#import

int OnInit()
{   
    int r=ShellExecuteW(0, "Open",some_path + "myFile.exe", "", "", 1);
    if (r <= 32){   Alert("Shell failed: ", r); return(false);  }

    // some code
         
//---
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
 
   ObjectsDeleteAll(ChartID(),-1,-1);
}

Then, I tried using functions as follows:

#import "shell32.dll"
   int ShellExecuteW(int hWnd, string Verb, string File, string Parameter, string Path, int ShowCommand);
#import

#import "user32.dll"
  int RegisterWindowMessageA(string s);
  int SendMessage(int hWnd,int Msg,int wParam,int lParam);
  int SendMessageA(int hWnd,int Msg,int wParam,string lParam);
  int FindWindowA(string lpClassName, string lpWindowName);
#import

int OnInit()
{   
    int r=ShellExecuteW(0, "Open",some_path + "myFile.exe", "", "", 1);
    if (r <= 32){   Alert("Shell failed: ", r); return(false);  }

    // some code
         
//---
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
   // METHOD-A
   int r2=SendMessageA(FindWindowA(NULL,"myFile.exe"),16,0,0);

   // METHOD-B
   int r3=ShellExecuteW(0, "TAKSKILL /IM", "myFile.exe", "", "", 1);

   // METHOD-C
   int r4=ShellExecuteW(0, "TAKSKILL /F /IM", "myFile.exe", "", "", 1);

   ObjectsDeleteAll(ChartID(),-1,-1);
}

None of the methods A, B, C could close that running myFile.exe.


Am I missing something?

Kindly help

Thanks

 
testsid: Am I missing something?
int r2=SendMessageA(FindWindowA(NULL,"myFile.exe"),16,0,0);

All strings are Unicode since Build 600.

 

I replaced

int r2=SendMessageA(FindWindowA(NULL,"myFile.exe"),16,0,0);

by

int r2=SendMessageW(FindWindowW(NULL,"myFile.exe"),16,0,"");

myFile.exe stops proceeding further now!

However, that .exe window still does not get closed :(

 
testsid: However, that .exe window still does not get closed :(

You killed the executable, why does that surprise you?

 
William Roeder:

You killed the executable, why does that surprise you?

Yes, you are correct. The .exe does not proceed further.

However, that .exe window is not closed. Also, I can see in my Task Manager that the .exe is actually running in the background consuming a good percentage of my system memory.

Also, if I wish to detach my EA from this chart & attach it to another chart, then it would show error because one instance of the .exe is still running in the background.

 

I also tried using CreateProcess() instead of ShellExecuteW() to run the .exe as a process, so that I may stop it by TerminateProcess().

(As mentioned in https://www.mql5.com/en/forum/131239)

However, the CreateProcess() is also showing some invalid memory access issue.

How to pass a null pointer to a DLL?
How to pass a null pointer to a DLL?
  • 2011.01.16
  • www.mql5.com
I'm trying to call CreateProcess() from MQL, without success...
 

I tried the following 2 methods to create a process:


1) using CreateProcessW() :

#import "kernel32.dll"
   int CreateProcessW(string lpApplicationName, 
                      string lpCommandLine, 
                      int lpProcessAttributes, 
                      int lpThreadAttributes, 
                      int bInheritHandles, 
                      int dwCreationFlags, 
                      int lpEnvironment, 
                      string lpCurrentDirectory, 
                      int & lpStartupInfo[], 
                      int & lpProcessInformation[]);
#import

int OnInit()
{   
   // Create an array to mimic a STARTUPINFO structure, which is 68 bytes long 
   int startupinfo[17];
   
   // Set the cb value of the STARTUPINFO structure. All the other values can
   // be left set to zero
   startupinfo[0] = 17 * 4;
   
   // Create an array to mimic a PROCESS_INFORMATION structure. Doesn't need
   // initialisation
   int processinfo[4];
   
   // Call create process
   if (CreateProcessW(NULL, some_path+"myFile.exe", 0, 0, 0, 0, 0, ".", startupinfo, processinfo) != 0) {      
      Print("myFile.exe started");
   } else {
      Print("CreateProcess() failed");
   }

    // some code
         
//---
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
 
   ObjectsDeleteAll(ChartID(),-1,-1);
}

However, it crashes when attached to MT5 chart. The error messages displayed in MT5 client terminal journal are as follows:

Access violation at 0x00007FF9049C8E06 read to 0x0000000000007FF7
       crash -->  00007FF9049C8E06 6644390442        cmp        [rdx+rax*2], r8w
                  00007FF9049C8E0B 75F6              jnz        0x7ff9049c8e03
    
                  00007FF9049C8E0D 483DFE7F0000      cmp        rax, 0x7ffe
                  00007FF9049C8E13 7711              ja         0x7ff9049c8e26
                  00007FF9049C8E15 6603C0            add        ax, ax
                  00007FF9049C8E18 668901            mov        [rcx], ax
                  00007FF9049C8E1B 6683C002          add        ax, 0x2

00: 0x00007FF9049C8E06
01: 0x00007FF9025F79EA
02: 0x00007FF9025F9BCD
03: 0x00007FF9025F67B6
04: 0x00007FF902D2BE93
05: 0x000001A228A58C9A


2) using CreateProcessA():

#import "kernel32.dll"
   int CreateProcessA(int    lpApplicationName,
                      string lpCommandLine,
                      int &   lpProcessAttributes[],
                      int &   lpThreadAttributes[],
                      int    bInheritHandles,
                      int    dwCreationFlags,
                      int    lpEnvironment,
                      int    lpCurrentDirectory,
                      int &    lpStartupInfo[],
                      int &  lpProcessInformation[]);
#import

int OnInit()
{
   string lpCommandLine = some_path+"myFile.exe";

   int /*SECURITY_ATTRIBUTES*/ sa[ 3] = {12};
   int /*STARTUPINFO*/         si[17] = {68};
   int /*PROCESS_INFORMATION*/ pi[ 4];

   int result2 = CreateProcessA(NULL,            // module name
                               lpCommandLine,   // command line
                               sa,              // process attributes
                               sa,              // thread attributes
                               false,           // handle inheritance
                               0,               // creation flags
                               NULL,            // environment block
                               NULL,            // starting directory
                               si,              // startup info
                               pi               // process info
   );

   if (result2 == 0) {
      Print("CreateProcess() failed with error");
   }
   else {
      Print("CreateProcess() success");
   }

         
//---
   return(INIT_SUCCEEDED);
}

void OnDeinit(const int reason)
{
//---

   ObjectsDeleteAll(ChartID(),-1,-1);
}

On running this, no memory access violation is reported. However, the following is displayed in journal message:

CreateProcess() failed with error
I basically want to open the .exe from OnInit(), store some handle value of the opened .exe in a global variable & close that opened .exe from OnDeInit() using that handle value


Kindly help

Thanks

Reason: