I want to ensure that my logic is correct here. I want to run a process for timeout
seconds, if it runs for longer it should be immediately killed.
The completed
flag should reliably indicate whether the process completed as intended, e.g was not killed, and did not crash or throw an exception.
Also, I am not positive if the check to process.HasExited
is correct. If process.WaitForExit()
returns false and Kill()
succeeds, then will process.HasExited
always be true? That would be my assumption but I wanted to confirm. Also, what if anything can be done if Kill() fails,
besides just logging?
using (process = new Process())
{
process.EnableRaisingEvents = true;
process.OutputDataReceived += new DataReceivedEventHandler(OnOutputDataReceived);
process.ErrorDataReceived += new DataReceivedEventHandler(OnErrorDataReceived);
process.Exited += new EventHandler(OnExited);
process.StartInfo = startInfo;
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
if (!process.WaitForExit(timeout))
{
try
{
process.Kill();
}
catch (Exception e)
{
LogError(e, MethodBase.GetCurrentMethod());
}
finally
{
this.completed = false;
}
}
else
{
if (process.HasExited)
{
this.code = process.ExitCode;
this.completed = true;
}
else
{
this.completed = false;
}
}
}
Yes, the HasExited will always be true in your case.
According to MSDN,
"A value of true for HasExited indicates that the associated process has terminated, either normally or abnormally.[...]A process can terminate independently of your code. If you started the process using this component, the system updates the value of HasExited automatically, even if the associated process exits independently."
However, if your process crashes and terminates before your timeout, then your code will set it as completed anyway. Maybe you should check the exit code, but it can have different meanings for each process:
if (process.ExitCode != 0)
{
this.completed = false;
}
For crashes, there are some approaches here and here, but generally you can't detect crashes for all processes.
We use the following in a .net console app
private void InitTimer()
{
double lInterval = Convert.ToDouble(AppSettings("MaxExecutionTime"));
lInterval = lInterval * 60 * 1000;
tm = new System.Timers.Timer(lInterval); // global timer object
tm.Elapsed += OnTimedEvent;
tm.Enabled = true;
}
public void ThreadProc(object stateinfo)
{
// set error code here
Environment.Exit(0);
}
private void OnTimedEvent(object source, ElapsedEventArgs e)
{
Threading.ThreadPool.QueueUserWorkItem(new Threading.WaitCallback(ThreadProc));
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With