The default configuration when launching a process is the child remains connected to the terminal of the parent process.
When the application shouldn't interact with the user, it is preferable to have an easy way to disconnect the child from the terminal.
This can done by adding the following properties to ProcessStartInfo:
``c#
// semantics of
// This is: the child can read from standard in. Reading from standard in returns 0 bytes, i.e.: EOF.
// alternative names: NoStandardInput/CloseStandardInput/StandardInputEOF
bool EmptyStandardInput;
// semantics of>/dev/null
// This is: the child can write to standard out. Anything written to standard out is ignored.
bool DiscardStandardOutput;
// semantics of2>/dev/null`
// This is: the child can write to standard error. Anything written to standard error is ignored.
bool DiscardStandardError;
// including request https://github.com/dotnet/corefx/issues/32387 in this API suggestion:
// semantics of 2>&1
// This is: the parent will read both standard error and standard output from Process.StandardOutput.
// This means the ordering used by the child when writing to standard error/out is preserved. (This is lost when reading from Process.StandardOutput and Standard.Error separately).
bool RedirectStandardErrorToStandardOutput;
**Example**
This starts `dotnet build` as a child process.
We set `EmtpyStandarInput` to `true`. Should the process try to read from stdin, it will not cause a prompt on the terminal, and read an EOF.
We also set `RedirectStandardErrorToStandardOutput` to `true`. This makes it possible to read both stdout and stderr from `Process.StandardOutput` together in the order the application wrote to those file descriptors.
```c#
var psi = new ProcessStartInfo
{
FileName = "dotnet",
Arguments = "build",
RedirectStandardErrorToStandardOutput = true,
EmptyStandardInput = true
};
using (var process = Process.Start(psi))
{
string output = process.StandardOutput.ReadToEnd();
}
CC @jhudsoncedaron
In general, this is a really good idea. I've emulated this with dumb pipes and background threads way too many times.
Starting process stdin/stdout/stderr closed is actually very badly defined on unix systems but glibc repairs this to avoid security vulnerabilities that have appeared in the past. Correct solution: replace the handle with a handle to /dev/null instead. You already have properties proposed to do this for standard output and standard error. So we need one more:
// semantics of `</dev/null`
bool EmptyStandardInput
Starting process stdin/stdout/stderr closed is actually very badly defined on unix systems but glibc repairs this to avoid security vulnerabilities that have appeared in the past. Correct solution: replace the handle with a handle to /dev/null instead.
Interesting. Updating proposed:
``c#
// semantics of<&-
bool CloseStandardInput
// semantics of1<&-
bool CloseStandardOutput
// semantics of2<&-`
bool CloseStandardError
// semantics of >/dev/null
bool DiscardStandardOutput
// semantics of 2>/dev/null
bool DiscardStandardError
// including request https://github.com/dotnet/corefx/issues/32387 in this API suggestion:
// semantics of 2>&1
bool RedirectStandardErrorToStandardOutput
to:
```c#
// semantics of `</dev/null`
bool EmptyStandardInput
// semantics of `>/dev/null`
bool DiscardStandardOutput
// semantics of `2>/dev/null`
bool DiscardStandardError
// including request https://github.com/dotnet/corefx/issues/32387 in this API suggestion:
// semantics of `2>&1`
bool RedirectStandardErrorToStandardOutput
The process that is started with EmptyStandardInput gets a readable standard in that is at the EOF.
Thanks @tmds. Can you please keep the top post updated with your proposal (since API review look there). You might also extend the text to a bit more match the format mentioned here
https://github.com/dotnet/corefx/blob/master/Documentation/project-docs/api-review-process.md
I've updated the top post with the most recent proposal, some additional info and an example.
As an alternative, which would enable even more, we could add properties that accept filenames for the redirects, and add a static sentinel filename for '/dev/null' that enables the EmptyStandardInput, DiscardStandardOutput, DiscardStandardError use-cases.
```C#
// Replacing EmptyStandardInput, DiscardStandardOutput, DiscardStandardError:
string RedirectStandardOutputTo;
string RedirectStandardInputTo;
string RedirectStandardErrorTo;
const string DevNull = "/dev/null";
// same as before
bool RedirectStandardErrorToStandardOutput;
```
DevNull feels wrong. NullFile or NullDevice would be better. I wonder which of these is actually better:
const string NullDevice = "/dev/null";
or
#if WINDOWS
static readonly string NullDevice = "NUL";
#else
static readonly string NullDevice = "/dev/null";
#endif
As an alternative, which would enable even more, we could add properties that accept filenames for the redirects, and add a static sentinel filename for '/dev/null' that enables the EmptyStandardInput, DiscardStandardOutput, DiscardStandardError use-cases.
Yes please. Supporting arbitrary filenames would add immense value to an already useful enhancement. Would you be able to update the OP and I'll see if I can get it in for API review.