Context
I'm using a .Net System.Diagnostic.Process object from Matlab to run, without any popping-up console window, some external processing for which I redirect, in real time, stdout/stderr to the matlab console (or any matlab progress-gui in the future).
The program to run is a .bat
file, that itself runs a python script (preprocessing.py) that finally internally calls an executable (processing.exe).
So far everything works great including redirection of stdout/stderr, except that when trying to stop execution on matlab side (with ctrl+c
), I can see from the task manager that the call to Process.Kill()
does not stop nor the python engine (python.exe) and nor the executable call by the python script (processing.exe). My matlab script is then blocked in Process.WaitForExit()
until I manually kill python.exe or processing.exe from the task manager.
Why the Kill() method on the initial System.Diagnostic.Process ran on .bat file does not kill the other child processes and makes me locked in WaitForExit ? ... I can force-kill processing.exe but it's dirty (I'm not supposed to know anything about possible child processes started).
The matlab code
Basically my matlab code looks like this:
function [] = main(guicallbacks)
%[
% Init process
process = System.Diagnostic.Process();
process.StartInfo.Filename = 'Processing.bat';
process.StartInfo.CreateNoWindow = true;
process.UseShellExecute = false;
process.RedirectStandardOutput = true;
process.RedirectStandardError = true;
% Attach to process events
l = event.listener(process, 'OutputDataReceived', @onStdOut); l.Recursive = true;
l = event.listener(process, 'ErrorDataReceived', @onStdErr); l.Recursive = true;
% Start process
Start(process);
cuo = onCleanup(@()stopProcess(process));
process.BeginOutputReadLine();
process.BeginErrorReadLine();
% Wait for process
canceled = false;
while (~double(process.HasExited))
% Check for cancellation (progress gui, etc...)
canceled = guicallbacks.IsCancelPending();
if (canceled), break; end
% Wait
pause(1.0);
end
% Check stop reason
if (canceled), error('System:OperationCanceledException', 'User cancelation'); end
if (double(process.ExitCode) ~= 0), error('Process failed (ExitCode = %i)', double(process.ExitCode)); end
%]
end
function [] = onStopProcess(process)
%[
if (double(process.HasExited())), return; end
process.Kill();
process.WaitForExit();
%]
end
function [] = onStdOut(varargin)
%[
cprintf('blue', char(varargin{2}.Data));
%]
end
function [] = onStdErr(varargin)
%[
cprintf('red', char(varargin{2}.Data));
%]
The .bat file
Basically, execept for setting a few environment variables the .bat
file to call looks like this:
python.exe -u preprocessing.py
The python script
The python script call final processing.exe executable this way:
subprocess.call("processsing.exe");
question from:
https://stackoverflow.com/questions/66067979/how-to-fully-stop-a-bat-file-and-child-processes-started-with-system-diagnost 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…