0

I have following situation. I need to run some bat file in c# using Process() and need to redirect it's out put end error to files. I know how to do it and my code works fine if I don't use timeout for my process. So the program works until the process ends (what I expect is the process being killed after timeout). The following is my code.

Process TcRunner = new Process();
TcRunner.StartInfo.FileName = "cmd.bat";
TcRunner.EnableRaisingEvents = true;
TcRunner.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
TcRunner.StartInfo.UseShellExecute = false;
TcRunner.StartInfo.RedirectStandardOutput = true;
TcRunner.StartInfo.RedirectStandardError = true;

try
{
     TcRunner.Start();
}
catch (Exception ex)
{
     Program.Print("Error: Could not start process\n");
     return 1;
}

string run_log_out = TcRunner.StandardOutput.ReadToEnd();
string run_log_err = TcRunner.StandardError.ReadToEnd();

if (!TcRunner.WaitForExit(5000)
{
    //kill the process
}

try
{
    StreamWriter run_out = new StreamWriter(@".\out");
    StreamWriter run_err = new StreamWriter(@".\err");
    run_out.WriteLine(run_log_out);
    run_err.WriteLine(run_log_err);
    run_out.Close();
    run_err.Close();
}
catch (Exception e)
{
    Console.WriteLine("Cannot open out/err for writing");
}
Gayane
  • 627
  • 1
  • 11
  • 23
  • Can you explain the problem a bit more? – Dieter Meemken May 10 '16 at 08:03
  • The program hangs on line string run_log_out = TcRunner.StandardOutput.ReadToEnd(); until process end then moves to line waitforexit(timeout). So if I have timeout 5 seconds the and my command runtime is 10 seconds the process will not be killed – Gayane May 10 '16 at 08:52

1 Answers1

0

if you want to read both stream syncronously, there is a possibility for a deadlock. So, you should try to read at least one stream asyncronously.

In the VisualStudio Help for ProcessStartInfo.RedirectStandardOutput, i found this info:

   // Do not perform a synchronous read to the end of both
   // redirected streams.
   // string output = p.StandardOutput.ReadToEnd();
   // string error = p.StandardError.ReadToEnd();
   // p.WaitForExit();
   // Use asynchronous read operations on at least one of the streams.
   p.BeginOutputReadLine();
   string error = p.StandardError.ReadToEnd();
   p.WaitForExit();

This link has a good example, where they read both streams asyncronously by binding a method to the events:

...
build.StartInfo.RedirectStandardOutput = true;
build.StartInfo.RedirectStandardError = true;
...
build.ErrorDataReceived += build_ErrorDataReceived;
build.OutputDataReceived += build_ErrorDataReceived;
...
build.BeginOutputReadLine();
build.BeginErrorReadLine();

static void build_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
    ...
} 
Community
  • 1
  • 1
Dieter Meemken
  • 1,937
  • 2
  • 17
  • 22