[Mono-dev] System.Diagnostics.Process behaves differently in and outside of a NUnit test case

Dan Liew dan at su-root.co.uk
Thu Oct 15 16:23:37 UTC 2015


Hi Ludovic,

On 15 October 2015 at 12:47, Ludovic Henry <ludovic at xamarin.com> wrote:
> Hi Dan,
>
> As I am currently working on the Process class, I am getting a look at your
> bug.

Thanks for taking a look :)

>
> Does setting  StandardOutputEncoding = Console.OutputEncoding on the
> ProcessStartInfo passed to Start fixes your issue? This is the behaviour on
> .NET, so this is the behaviour that we are going to adopt (at least for bug
> compatibility).

For the version of mono I'm currently using (4.0.4) doing this doesn't work

```
StartInfo = new ProcessStartInfo(PathToSolverExecutable);
StartInfo.Arguments = solverArguments;
StartInfo.RedirectStandardInput = true; // Neccessary so we can send our query
StartInfo.RedirectStandardOutput = true; // Necessary so we can read the output
StartInfo.RedirectStandardError = true;
StartInfo.UseShellExecute = false; // C# docs say this is required

// This is a HACK
TheEncoding = new System.Text.UTF8Encoding(/*
encoderShouldEmitUTF8Identifier=*/ false);
StartInfo.StandardOutputEncoding = TheEncoding;
```

The standard input stream is still sending the UTF-8 BOM. But doing
this before creating the process
works.

```
Console.OutputEncoding = new System.Text.UTF8Encoding(/*
encoderShouldEmitUTF8Identifier=*/ false);
```

The only reason I knew to do this is because I looked at the
implementation of ``System.Diagnostics.Process`` on my system
and saw that this the encoding that is being used comes from
``Console.Out.Encoding`` and took a guess that if I modified
``Console.OutputEncoding`` the change "might" propagate to
``Console.Out.Encoding``. Here's the implementation code I
was looking at.

```
if (startInfo.RedirectStandardInput == true) {
MonoIO.Close (stdin_rd, out error);
process.input_stream = new StreamWriter (new MonoSyncFileStream
(stdin_wr, FileAccess.Write, true, 8192), Console.Out.Encoding);
process.input_stream.AutoFlush = true;
}
```

However I've noticed that the code in the master branch of mono is
different. At a glance it looks like it's using
``startInfo.StandardOutputEncoding``
if it's not null

```
if (startInfo.RedirectStandardOutput) {
MonoIO.Close (stdout_write, out error);
Encoding stdoutEncoding = startInfo.StandardOutputEncoding ??
Console.Out.Encoding;
process.output_stream = new StreamReader (new FileStream (new
SafeFileHandle (stdout_read, false), FileAccess.Read, 8192, false),
stdoutEncoding, true, 8192);
}
```

So it looks like a nicer workaround is now available (I've not tested
it though). It's a bit of a pain though as I can't rely on it in older
versions of mono which means I have to use my horrible hack anyway :(


Please note that the bug I filled about NUnit [1] has had a response.
It sounds like NUnit is deliberately changing the encoding
on standard output because they expect that it being redirected to a file.

[1] https://github.com/nunit/nunit/issues/881


More information about the Mono-devel-list mailing list