用C#捕获cmd执行plink的ALL(stdout,stderr AND CON)输出(stdout+err ok,C
本文关键字:stderr AND CON 输出 ok stdout+err stdout cmd 捕获 执行 plink | 更新日期: 2023-09-27 18:21:01
我想通过打开一个进程并运行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(AttachConsole
、WriteConsole
等),每个进程只能有一个"控制台"。
另一方面,CMD.EXE
只是另一个控制台模式的应用程序,它恰好使用控制台,并在控制台窗口中启动它。您可以通过启动不同的控制台模式应用程序来观察这种效果,并在例如process Explorer中观察进程树:没有CMD.EXE父进程(而是Explorer或您用来启动它的任何程序,当然包括CMD.EXE)
到目前为止,我试图展示"控制台"和CMD.EXE
、批处理文件或控制台模式应用程序之间的区别。
因此,当在CMD.EXE
中使用> CON
时,实际上会产生与在本机应用程序中写入CONOUT$
(或在类似UNIX的操作系统上写入/dev/console
)相同的效果。托管代码似乎没有直接的等价物,因为Console.Out
和Console.Error
在本机应用程序中等于stdout
和stderr
(或者1
和2
作为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(),我不确定是否可以重定向它。