Отправить TAB на дочернюю консоль (windows) - PullRequest
2 голосов
/ 11 апреля 2009

Я создаю дочернее консольное приложение с

_process = new Process();
_process.StartInfo.FileName = @"cmd.exe";
_process.StartInfo.UseShellExecute = false;
_process.StartInfo.RedirectStandardInput = true;
_process.StartInfo.RedirectStandardOutput = true;
_process.StartInfo.CreateNoWindow = true;

_proccess.Start();

Теперь я могу перейти к c: \ aaa

_process.StandardInput.Write("cd c:\\aaa\xD\xA");

Но обычно пользователь может набрать c: \ + TAB + ENTER. Как я могу сделать то же самое? Это не работает:

_process.StandardInput.Write("cd c:\\\0x9\xD\xA");

Ответы [ 2 ]

2 голосов
/ 01 марта 2011

Существует принципиальная разница между стандартным входом дочернего процесса и консолью, к которой он подключен. Интерпретатор команд в интерактивном режиме ожидает разговора либо с консолью или с каналом / файлом в качестве стандартного ввода, и он меняет свое поведение в соответствии с тем, которое находит. Для канала / файла он просто вызывает функцию ReadFile(). Однако для консоли она получает ввод через ReadConsoleInput(), где не буквенно-цифровые ключи распознаются по их кодам виртуальных клавиш.

См., Например, функцию ReadCommand() в ReactOS CMD.

Если вы записываете байт со значением 9 по конвейеру на стандартный ввод процесса, это то, что он увидит после вызова ReadFile(). Но это не будет восприниматься как нажатие клавиши Tab , потому что (для начала) оно не одно; это просто значение байта 9, идущее вниз по трубе. Кроме того, редактирование командной строки, которое выполняет интерпретатор команд в интерактивном режиме, происходит только тогда, когда стандартный ввод определяется как консоль, а не когда это канал или файл. Интерпретатор команд использует ReadConsoleInput(), который не читает буферы байтов, а читает последовательности INPUT_RECORDs; и, таким образом, вам нужно WriteConsoleInput() для этой консоли обрабатывать соответствующую INPUT_RECORD, имитирующую клавишу Tab , если вы хотите, чтобы интерпретатор команд видел нажатие клавиши Tab во входном потоке.

Конечно, поскольку вы установили StartInfo.RedirectStandardInput на true, под крышками .NET подключил стандартный ввод процесса интерпретатора команд к каналу; и поэтому интерпретатор команд просто вызывает ReadFile(), без какого-либо интерактивного редактирования командной строки, как если бы его стандартный ввод был консолью. Даже если бы вы могли найти и открыть дескриптор консоли процесса интерпретатора команд и записать INPUT_RECORD для клавиши Tab , интерпретатор команд читает канал для своего стандартного ввода и игнорирует его консоль.

Если вы хотите, чтобы интерпретатор команд работал так же, как если бы он разговаривал с консолью, редактировал командную строку и все такое, вы должны запустить процесс со стандартным вводом в качестве консоли , чья ручку, которую вы должны (затем) получить, чтобы имитировать нажатия клавиш с помощью WriteConsoleInput(). Это довольно сложно в .NET.

1 голос
/ 23 марта 2010

Как насчет погружения в Windows API?

using System.Runtime.InteropServices;
//...
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, IntPtr lParam);
private const int WM_CHAR = 0x0102;
private const int VK_TAB = 0x9;
private const int VK_RETURN = 0xD;
//...
SendMessage(_process.Handle, WM_CHAR, new IntPtr(VK_TAB), new IntPtr(0));
SendMessage(_process.Handle, WM_CHAR, new IntPtr(VK_RETURN), new IntPtr(0));

Однако это не всегда работает согласно ответ Кевина Монтроуза здесь .

...