3

i am invoking an exe via c# Diagnostics.Process class and read output from it's StdOut. The process is forcefully terminated in case it doesn't automatically terminates in a specified time, something like:

process.StartInfo.FileName = @"D:\t.exe";
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = false;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = false;

process.WaitForExit(500);

if (!process.HasExited)
{
    process.Kill();
    process.WaitForExit();
}
string stdOutContents = process.StandardOutput.ReadToEnd();

Now the problem is the code works succesfully when the exe terminates normally. But in case it fails to terminate normally (usually the exe gets stuck in an infinite loop somewhere), stdOutContents is read as an empty string.

How can i read StdOut after the process is killed (without using process.OutputDataReceived event technique)? (It has been verified that the exe-in-question does always writes something onto StdOut even if it gets stuck somewhere).


Update 1

Details about Exe which is being invoked (refereed as 'native app' across this question)

It is a small utility implemented in c language and compiled using MS C++ compiler. It does its job while simultaneously outputting status information onto the StdOut (using putchar).

There are only two possible cases of operation:

  1. It will run successfully while simultaneously printing some data onto the StdOut.
  2. It will run normally to a certain point (simultaneously outputting data on StdOut) and then get stuck in an infinite loop. (This is an acceptable behavior).

Both scenarios have been verified using cmd.

Details about new attempts

i wrote a c# app (referred as dummy app) which mimics the native app behavior and this code works fine. However when run for the native app, i get nothing at all.

i don't understand why the code cant read the contents outputted by the native app?

i also tried using event handler for OutputDataReceived. It gets called only once with args.Data = null when the code tries to kill the process. Inspecting the behavior for dummy app revealed that when process.kill is called, the handler is invoked with args.Data = null. So this seems to be a standard behavior of sorts for both apps.

i also tried changing the newline characters for native app. Since it is implemented in c language, it uses \n for newline. i tried using both \r\n pair for newline but StdOut is still blank (for case 2).

  • Hm... I've used an infinite loop which writes an value to the console every 50 ms as t.exe. It works fine here... Have you tried using the event handlers for debugging reasons? In this way you could verify that the process does indeed write something into it's output stream. – Markus Safar Nov 04 '13 at 09:07

1 Answers1

1

I had the same interrogation and the doc of Process.Kill says

Data edited by the process or resources allocated to the process can be lost if you call Kill.

Which seems to indicate that you cannot rely on reading the StandardOutput of a process, although it is not clearly stated that the output / error streams are disposed.

I finally got inspired by this answer How to spawn a process and capture its STDOUT in .NET?

and I use the following code :

var info = new ProcessStartInfo("some.exe");
info.CreateNoWindow = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;

using (var p = new Process())
{
    p.StartInfo = info;
    var output = new StringBuilder();
    p.OutputDataReceived += (sender, eventArgs) =>
    {
        output.AppendLine(eventArgs.Data);
    };
    p.Start();
    p.BeginOutputReadLine();
    if (!p.WaitForExit(5000))
    {
        Console.WriteLine("Taking too long...");
        p.Kill();
        Console.WriteLine("Process killed, output :\n" + output);
    }
}

Same pattern can be used with the ErrorDataReceived

Note that one could miss some unflushed output from the child process, however in my case I don't expect much from a process that requires to be killed, at most some information for debugging purposes.

Community
  • 1
  • 1
Wasabi
  • 456
  • 1
  • 4
  • 12