There's a fundamental difference between the standard input of the child process, and the console that it is attached to. A command interpreter in interactive mode is expecting to be talking either to a console or to a pipe/file as its standard input, and it changes its behaviour to match which one it finds. For a pipe/file, it just makes a simple call the ReadFile()
function. For a console, however, it receives input through ReadConsoleInput()
, where non-alphanumeric keys are recognizable by their virtual key codes.
See the ReadCommand()
function in the ReactOS CMD
for an example.
If you write a byte with the value 9 down a pipe to the standard input of a process, that's what it will see from its call to ReadFile()
. But it won't treat it as a Tab keypress, because (for starters) it isn't one; it's just byte value 9 coming down a pipe. Moreover, the command-line editing that a command interpreter does in interactive mode only occurs when the standard input is detected to be a console, not when it is a pipe or a file. The command interpreter uses ReadConsoleInput()
, which doesn't read buffers of bytes but reads sequences of INPUT_RECORDs
; and thus you have to WriteConsoleInput()
to that console handle an appropriate INPUT_RECORD
simulating the Tab key if you want the command interpreter to see a Tab keypress in its input stream.
Of course, since you've set StartInfo.RedirectStandardInput
to true
, under the covers .NET has connected the standard input of the command interpreter process to a pipe; and so the command interpreter is just calling ReadFile()
, without doing any interactive command-line editing, as it would if its standard input had been a console. Even if you could find and open a handle to the command interpreter process' console, and write a INPUT_RECORD
for a Tab key to it, the command interpreter is reading a pipe for its standard input, and ignoring its console.
If you want a command interpreter to act just as it would if it were talking to a console, command line editing and all, you have to spawn the process with its standard input as a console, whose handle you have to (then) obtain so that you can simulate keypresses with WriteConsoleInput()
. That's fairly difficult within .NET.