I have a .NET 8.0 executable under Windows 11 that starts another executable and then listens for its output:
public static int Main(string[] args)
{
var executable = @"hardcoded path to childprocess.dll";
var psi = new ProcessStartInfo(executable)
{
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
using var process = Process.Start(psi)!;
process.OutputDataReceived += (_, dataReceivedEventArgs) => ProcessOnOutputDataReceived(dataReceivedEventArgs, Console.Out);
process.BeginOutputReadLine();
process.WaitForExit();
return process.ExitCode;
}
private static void ProcessOnOutputDataReceived(DataReceivedEventArgs args, TextWriter textWriter)
{
// never called for Console.Write + Flush
// called without issues with Console.WriteLine
if (args.Data is var data and not null)
{
textWriter.WriteLine(data);
}
}
This works fine if the child process uses Console.WriteLine
, but I can't get it to work with Console.Write + Flush
, which I'd imagine would be equivalent.
public static void Main(string[] args)
{
Console.Write("Output never visible :(");
Console.Out.Flush();
// Console.WriteLine("This works perfectly fine!");
Console.ReadLine(); // just to stop the process from quitting.
}
Debugging the code I see that _autoFlush
is enabled anyhow, so I shouldn't even need the explicit Flush afterwards.
For the flush we end up in ConsolePal::WriteFileNative
with useFileAPIs
set to true which means we end up calling Kernel32.WriteFile
which returns the correctly written number of characters.
Calling FlushFileBuffers
with the file handle makes no difference either.
BeginOutputReadLine
in the parent process waits for a newline to complete the line and trigger the OutputDataReceived
event. Without a newline, the OutputDataReceived
event will not be raised.
You need a different approach to read the output from the console. One way could be using unbuffered reads like:
var psi = new ProcessStartInfo(executable)
{
RedirectStandardOutput = true,
UseShellExecute = false,
CreateNoWindow = true
};
using var process = Process.Start(psi)!;
using var reader = process.StandardOutput;
int nextChar;
while ((nextChar = reader.Read()) != -1)
{
char c = (char)nextChar;
Console.Write(c); // Process or write each character as it arrives
}
process.WaitForExit();