Run Win32 executable and get status of completion...
16 views (last 30 days)
Show older comments
Hi all,
I'm setting up an function that runs several Win32 executables (depending on the number of cores I have available) using matlab system function. The result is a bunch of DOS windows indicating the progress of the program which are closed automatically when the program finishes or crash. The next steps of the function are: (1) detect when each executable stop, (2) confirm that all the files where successfully created and (3) update a log file. While (2) and (3) are easy to address, I'm stuck in (1). I though that, by using:
[status, result] = system('command')
I would get any information regarding the end of the executable run, but this is not the case, as status/result variables are not updated in the end. Could someone please provide me a clue on how can I address this issue!
Thanks in advance!!
2 Comments
Rik
on 28 Sep 2017
Doesn't system usually only return after the process is complete? (unless your code starts something else that detaches)
Answers (2)
dpb
on 28 Sep 2017
Edited: dpb
on 28 Sep 2017
I answered this in your question added to the other thread; this confirms the issue is the one I addressed there -- Win32 programs don't have a console and so don't write anything to stdout so you can't get any information back this way from the program inside the detached process.
You could try to wrap the program call in a batch file that returns a status itself but there again you likely run into "issues" trying to tell whether the program terminated normally or not.
About the only way to do something like this for a program that wasn't designed for interprocess communication is for it to be able to write a log file or some other static object that the dispatching process can query or, use the TASKLIST command utility to search for the given process. This would entail dispatching that task periodically to check on status.
Alternatively, one could write a mex routine using system API calls to do this internally from Matlab or perhaps someone has already done it -- might search on the File Exchange to see. There are bound to be other system monitor routines available that could be used but I've not looked for any specifically.
ADDENDUM
It wouldn't be too hard to wrap the CMD TASKLIST utility in an m-file as a rudimentary tool to accomplish the goal...
function isfound=istaskrunning(task)
% returns TRUE if executable image name is found and status running
% SYNTAX:
% logicalResult = istaskrunning(TASK)
% returns T for if TASK input as string presently running
%
cmd = sprintf('tasklist /FI "IMAGENAME eq %s" /FI "STATUS eq running"',task);
[stat,res]=system(cmd);
isfound=~isempty(strfind(lower(res),lower(task)));
Sample use...
>> task='matlab.exe'; % is a matlab session running?
>> istaskrunning(task) % result of query is True (yes)
ans =
1
>> istaskrunning('junk.bat') % try something know isn't extant
ans =
0
and the latter is False as should be.
You can do more sophisticated searches including a PID for a specific process or the window title if you were to start each process with a unique title besides just the executable name in order to identify the specific instances you're after.
8 Comments
dpb
on 4 Oct 2017
Well, it's undoubtedly do-able; Jan looked into Java as way to get to the internals of the OS APIs; I don't know much about that for where to get the doc to look it up so let him go that route...
I'm curious about the result of the above, however, what do you see at the Applications level instead of Processes? Was/Is my supposition correct in that regards?
Jan
on 4 Oct 2017
Edited: Jan
on 30 Dec 2020
exeFile = 'c:\temp\example.exe';
startInfo = System.Diagnostics.ProcessStartInfo('cmd.exe', ...
sprintf('/c "%s"', exeFile));
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
proc = System.Diagnostics.Process.Start(startInfo);
if isempty(proc)
error('Failed to launch process');
end
while true
if proc.HasExited
fprintf('\nProcess exited with status %d\n', proc.ExitCode);
break
end
fprintf('.');
pause(1.0);
end
Does this help?
Or through Java:
exeFile = 'c:\temp\example.bat';
cmd = sprintf('cmd.exe /c "%s"', exeFile);
runtime = java.lang.Runtime.getRuntime();
proc = runtime.exec(cmd);
% a = proc.getInputStream;
% b = proc.getOutputStream;
while true
% a.read; % Causes a stall on my machine?!
% b.flush;
try
exitCode = proc.exitValue();
fprintf('\nProcess exited with status %d\n', exitCode);
break;
catch
err = lasterror(); % old syntax for compatibility
if strfind(err.message, 'process has not exited')
fprintf('.');
pause(.1);
else
rethrow(err);
end
end
end
Or
runtime = java.lang.Runtime.getRuntime();
process = runtime.exec('program arg1 arg2'); % non-blocking
% rc = process.waitFor(); % block Matlab until external program ends
% rc = process.exitValue(); % fetch an ended process' return code
% process.destroy(); % Kill process prematurely
3 Comments
Jan
on 9 Nov 2017
@Joao: Which of the three approaches I had posted do you mean? The first one blocks Matlab only, because the "while true" loop runs until proc.HasExited is true. Of course you can omit this loop and check the status anywhere else. The last method is also non-blocking.
Is there a possibility to use something like
system('start /MIN Mohid.exe')
Perhaps, but then there is no way to check reliably, if the functions have finished correctly. Therefore I'd prefer either the java runtime.exec or the .NET Process.Start.
I do not understand the detail about the status. Where is what shown and what is the problem?
See Also
Categories
Find more on Debugging and Analysis in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!