Захватить ВСЕ (вывод stdout, stderr и CON) команды cmd, выполняющей plink с помощью C # (std out + err ok, CON не работает) - PullRequest
7 голосов
/ 23 января 2012

Я хочу открыть SSH-соединения из c #, открыв процесс и запустив plink. Весь вывод должен быть собран и в зависимости от результатов программа запустит действия в ssh. Моя большая проблема в том, что я использую пару, если разные сценарии, и мне нужно (автоматизированное) взаимодействие с пользователем. Поэтому мне нужно захватить ВСЕ выходные данные (стандартный вывод, стандартная ошибка И КОНСОЛЬ).

Глядя на следующую тестовую партию, следует прояснить ситуацию:

1: @ECHO OFF
2: ECHO StdOut
3: ECHO StdErr 1>&2
4: ECHO Cons>CON

Код похож на:

Process process;
Process process;
process = new Process();
process.StartInfo.FileName = @"cmd.exe";
process.StartInfo.Arguments = "/c test.bat";
process.StartInfo.UseShellExecute = false;
process.StartInfo.ErrorDialog = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
process.Start();
process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
process.ErrorDataReceived += new DataReceivedEventHandler(process_OutputDataReceived);
process.BeginOutputReadLine();
process.BeginErrorReadLine();
StreamWriter inputWriter = process.StandardInput;
[...]

Я могу захватить строки 2 + 3, но не 4 (используется некоторыми программами). Я также попытался использовать PowerShell (или непосредственно Plink) вместо cmd.exe в качестве отправной точки, но тот же результат.

Есть ли в c # какой-нибудь способ также захватить консоль, или вам известна какая-либо сторонняя командная строка, способная перенаправить CON на stdout или что-то в этом роде?

Ответы [ 3 ]

7 голосов
/ 23 января 2012

Я не уверен, что это даже возможно - по крайней мере, не используя какой-то простой простой API.

Обратите внимание, что я не нашел (хотя я пытался) никакой информации в Интернете, которая прямо подтверждает это , но вот как я пришел к такому выводу.

Консоль в Windows является собственной подсистемой, управляемой csrss.exe (и начиная с Windows Vista также conhost.exe, но я отвлекся). Он имеет свой собственный набор API (AttachConsole, WriteConsole и т. Д.), И вы можете иметь только одну «консоль» на процесс.

CMD.EXE с другой стороны, это просто еще одно приложение в режиме консоли, которое просто использует консоль и запускает ее в окне консоли. Вы можете наблюдать этот эффект, запустив другое приложение режима консоли и наблюдая за деревом процессов, например, Process Explorer: родительский процесс CMD.EXE отсутствует (скорее это Explorer или что-то еще, что вы использовали для его запуска - включая, конечно, CMD.EXE).

До сих пор я пытался показать разницу между «консолью» и CMD.EXE, пакетными файлами или приложениями консольного режима в целом.

Поэтому, когда в CMD.EXE вы используете > CON, вы фактически вызываете тот же эффект, что и запись в CONOUT$ в собственных приложениях (или обычную запись в /dev/console в UNIX-подобной ОС). Кажется, что нет прямого эквивалента для управляемого кода, так как Console.Out и Console.Error равны stdout и stderr в собственных приложениях (или 1 и 2 как дескрипторы файлов в CMD.EXE) .

С учетом всего вышесказанного, когда вы запускаете процесс, вы можете только перенаправлять его стандартные выходные данные и стандартные потоки ошибок, но не (по сути) сообщения, которые он записывает на консоль (или дескриптор CONOUT$). Я думаю, это было бы то же самое, что пытаться перенаправить вывод, который процесс записывает в какой-либо файл, что также (вообще) невозможно.

Этого можно достичь, используя некоторые перехваты или вводя что-то внутри дочернего процесса, чтобы получить вывод консоли.

Отсутствие возможности легко сделать это также (одна из) причин (ы), почему написать полную замену терминала (т. Е. Окна консоли, а не CMD.EXE!) Для Windows нелегко и требует некоторых хаков или обходные пути.

3 голосов
/ 23 января 2012

AFAIK знает, что вы хотите (перенаправление CON) возможно только путем перехвата / инъекции, что довольно сложно и в принципе не является необходимым для выполнения SSH.

Для SSH вы можете использовать любое количество библиотек C # (бесплатных и коммерческих):

Основным преимуществом использования библиотеки является то, что вы имеете намного больший контроль над сеансом SSH, чем когда-либо, используя какую-либо перенаправленную консоль, И это намного проще реализовать ...

ОБНОВЛЕНИЕ - согласно комментариям:

Чтобы получить весь вывод из удаленно работающей программы, вам нужно использовать библиотеку, которая поставляется с классом «интерактив / терминал» для SSH - например, библиотека по http://www.rebex.net/ssh-pack/default.aspx поставляется с таким классом и действительно работает отлично (не аффилированный, просто счастливый клиент), его можно использовать как компонент только для кода или как визуальный контроль (все, что вам нужно).

0 голосов
/ 23 января 2012

Вот некоторые проекты CodeProject, которые делают это (через собственный код), которые AFAICT лучше обрабатывает, перенаправляя весь вывод консоли:

Универсальный консольный перенаправитель

Перенаправление произвольного ввода / вывода консоли

Также команда freopen позволяет программе перенаправлять свои потоки. Однако, если программа выполняет явный WriteConsole (), я не уверен, возможно ли это перенаправить.

...