使用C#捕获执行plink的cmd的所有(stdout,stderr和CON)输出(std out + err ok,CON not working)

时间:2012-01-23 07:10:17

标签: c# shell redirect console capture

我想通过打开进程并运行plink来打开来自c#的SSH连接。应收集所有输出,并根据结果,程序将触发对ssh的操作。 我的大问题是,我正在使用一对,如果不同的脚本,我需要(自动)用户交互。因此,我必须捕获所有输出数据(标准输出,标准错误和CONSOLE)。

查看以下测试批次应该使案例更清晰:

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 个答案:

答案 0 :(得分:7)

我不确定这是否可行 - 至少不使用简单的简单API。

请注意,我没有找到(虽然我尝试过)网上直接确认的任何信息,但这是我得出这个结论的方式。 < / p>

Windows中的控制台是它自己的子系统,由csrss.exe管理(从Windows Vista开始conhost.exe,但我离题了)。它有自己的设置API(AttachConsoleWriteConsole等),每个进程只能有一个“控制台”。

另一方面,

CMD.EXE只是另一个控制台模式应用程序,恰好使用控制台并将其启动到控制台窗口。你可以通过启动一个不同的控制台模式应用程序观察这种效果并观察例如Process Explorer:没有CMD.EXE父进程(而是它是资源管理器或你用来启动它的任何东西 - 当然包括CMD.EXE)。

到目前为止,我试图通常显示“控制台”和CMD.EXE,批处理文件或控制台模式应用程序之间的区别。

因此,在CMD.EXE中使用> CON时,实际上会产生与在本机应用程序中写入CONOUT$(或者对/dev/console的典型写入相同的效果一个类UNIX的操作系统)。似乎没有托管代码的直接等效项,因为Console.OutConsole.Error在本机应用程序中等于stdoutstderr(或1和{ {1}}作为2)中的文件描述符。

说完所有这些,当你启动一个进程时,你只能重定向它的标准输出和标准错误流,但不能(本身)它写入控制台(或CMD.EXE句柄)的消息。我想这与尝试重定向进程写入某个文件的输出相同,这也不是(一般)可能的。

您可以通过在子进程内部使用某些钩子或注入来获取控制台输出来实现此目的。

不能轻易做到这一点,也是(一个)为什么编写一个完整的终端(即控制台窗口,而不是CONOUT$!)替换Windows的原因之一(并且需要一些)黑客或解决方法。

答案 1 :(得分:3)

AFAIK知道你想要什么(重定向CON)只能通过挂钩/注入来实现,这是相当复杂的,基本上不需要做SSH。

对于SSH,您可以使用任意数量的C#库(免费和商业):

使用库的主要优点是,您可以通过某些重定向控制台实现对SSH会话的更大控制,并且更容易实现...

更新 - 根据评论:

要从远程运行的程序中获取所有输出,您需要使用一个带有“交互式/终端”类的SSH的库 - 例如http://www.rebex.net/ssh-pack/default.aspx的那个类带有这样的类并且工作得非常好(不是附加的,只是一个快乐的客户),它可以用作仅代码组件或视觉控件(适合您的需要)。

答案 2 :(得分:0)

以下是一些执行此操作的CodeProject项目(通过本机代码),AFAICT可以更好地处理重定向所有控制台输出:

Universal Console Redirector

Redirecting an arbitrary Console's Input/Output

此外,命令freopen允许程序重定向其流。但是,如果程序执行显式WriteConsole(),我不确定是否可以重定向它。