用C#捕获cmd执行plink的ALL(stdout,stderr AND CON)输出(stdout+err ok,C



我想通过打开一个进程并运行plink来打开来自c#的SSH连接。所有输出都应该被收集起来,根据结果,程序将向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或类似的东西?

我甚至不确定这是可能的——至少不使用一些简单的API。

请注意,我在网上没有发现(尽管我尝试过)任何直接证实这一点的信息,但以下是我得出这一结论的原因

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

另一方面,CMD.EXE只是另一个控制台模式的应用程序,它恰好使用控制台,并在控制台窗口中启动它。您可以通过启动不同的控制台模式应用程序来观察这种效果,并在例如process Explorer中观察进程树:没有CMD.EXE父进程(而是Explorer或您用来启动它的任何程序,当然包括CMD.EXE)

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

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

话虽如此,当你启动一个进程时,你只能重定向它的标准输出和标准错误流,但不能(本身)重定向它写入控制台(或CONOUT$句柄)的消息。我想这和试图将进程写入的输出重定向到某个文件是一样的,这(通常)也是不可能的。

您可以使用一些挂钩或在子进程中注入一些东西来获取控制台输出,从而实现这一点。

无法轻松做到这一点,也是为Windows编写一个完整的终端(即控制台窗口,而不是CMD.EXE!)替代品不容易实现的原因之一,需要一些技巧或解决方法。

AFAIK知道您想要什么(重定向CON)只有通过挂钩/注入才能实现,这相当复杂,基本上不需要执行SSH。

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

  • http://www.chilkatsoft.com/ssh-sftp-component.asp(商业)
  • http://www.tamirgal.com/blog/page/SharpSSH.aspx(免费)
  • http://sshnet.codeplex.com/(免费)
  • http://www.rebex.net/ssh-pack/default.aspx(商业)
  • http://www.eldos.com/sbb/desc-ssh.php(商业)

使用库的主要优点是,您对SSH会话的控制比通过重定向控制台实现的要大得多,而且实现起来也容易得多。。。

更新-根据评论:

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

以下是一些CodeProject项目,它们可以做到这一点(通过本机代码),AFAICT可以更好地处理重定向所有控制台输出:

通用控制台重定向器

重定向任意控制台的输入/输出

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

最新更新