No, unfortunately not. The example stringo pointed to is written in C++, not in MQL. In a native language it's not a problem at all. How to do this in MQL?
If MQL provides the use of native libraries it should be possible to pass a NULL pointer. So how?
Isn't there a solution with a single declaration?
Yes, of course passing directly 0 instead of an array works in this case. But what should I do in my next function call, where I indeed need to pass a valid struct. It's not possible to change back and forth declarations (if you need a NULL pointer change it to int, if you need to pass a struct/array change it to array).
Isn't there a solution with a single declaration?
To sum up: you can pass lpProcessAttributes and lpEnvironment as NULL by declaring them simply as int, and supplying 0 for these values. Your problem is that CreateProcess requires a non-null value for STARTUPINFO and PROCESS_INFORMATION. For example:
#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[]); int WaitForSingleObject(int Handle, int Timeout); #import int start() { // 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 (CreateProcessA(0, "c:\windows\system32\calc.exe", 0, 0, 0, 0, 0, 0, startupinfo, processinfo) != 0) { // Wait for calc.exe to be closed // Handle is in processinfo[0]; WaitForSingleObject(processinfo[0], 60 * 1000); MessageBox("Calc.exe started and closed..."); } else { MessageBox("CreateProcess() failed"); } }
The structs are not a problem. Structs are easy in MQL. The problems are lpApplicationName, lpCommandLine and lpDirectory. To get a working solution you have to define them as int and pass 0 or you define them as string. There is no unique solution for both ways.
Whenever your code indeed needs to specify module name or default directory your code breaks because you would have to change the declaration, and this is not possible. My simplified solution so far looked like this:
#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 start() { string lpCommandLine = "calc.exe"; int /*SECURITY_ATTRIBUTES*/ sa[ 3] = {12}; int /*STARTUPINFO*/ si[17] = {68}; int /*PROCESS_INFORMATION*/ pi[ 4]; int result = 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 (result == 0) { Print("CreateProcess() failed with error = "+ error); } else { Print("CreateProcess() success"); } return(0); }
I tried to keep the declaration as close as possible to the originial. I don't use NULL pointers for the structs, this way at least I can use/modify them.
So finally, as a clean and reusable solution I would recommend to implement the process creation either in a separate DLL or via ShellExecuteEx(), where we have no NULL pointers as parameters, only a struct that we can manipulate to our liking.
One more thing: Don't forget to close process and/or thread handles if you use CreateProcess() or ShellExecuteEx(). You asked for the references, so you are responsible to clean up afterwards.
@see CloseHandle()
Whenever your code indeed needs to specify module name or default directory your code breaks because you would have to change the declaration, and this is not possible.
I can't immediately think of a reason from MT4 why you might need to specify both lpApplicationName and lpCommandLine. Similarly, if you sometimes need to specify lpDirectory and sometimes not, then why can't you just declare it as string, and fill in the current directory when you would otherwise pass the value as null? What actual requirement do you have other than the one you've specified about needing a handle in order to call WaitForSingleObject()?
There is no unique solution for both ways
Yes, there is. It's just ridiculously and unnecessarily complex. You declare all the parameters as int, including the strings, and then get the addresses for the strings you want to pass and specify the others as zero. See https://www.mql5.com/en/forum/118999 for an example. But I can't see any actual reason why you'd need to go down this route.
So finally, as a clean and reusable solution I would recommend to implement the process creation either in a separate DLL or via ShellExecuteEx(), where we have no NULL pointers as parameters, only a struct that we can manipulate to our liking.
You can indeed use ShellExecuteEx(), but selectively populating the SHELLEXECUTEINFO from MT4 is very messy and again needs some nasty tweaks to get the addresses of the strings. Again, I'm struggling to see a plausible reason why, from MT4, you might need to do anything other than starting a process and getting back a handle.
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
I'm trying to call CreateProcess() from MQL, without success. Following is the import declaration:
lpProcessAttributes expexts a pointer to a SECURITY_ATTRIBUTES structure, usually NULL is passed. Same for lpThreadAttributes and lpEnvironment. But how to pass this NULL pointer. I know how to do it with strings.
Changing the declaration to
and passing 0 as pointer doesn't work. I know I can use WinExec() or ShellExecute() etc. to run an application but later I'm dependent on WaitForSingleObject(), so these are no options.Anybody any idea?