捕获使用 C# 执行 plink 的 cmd 的所有(stdout、stderr AND CON)输出(std out+err ok,CON 不起作用)

发布于 2024-12-28 05:19:03 字数 1187 浏览 4 评论 0原文

我想通过打开进程并运行 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 或类似的东西?

I want to open SSH connections from c# via opening a process and running plink. All output should be collected and depending on the results the program will fire actions to the ssh.
My big problem is, that i am using a couple if different scripts and i need (automated) user interaction. Therefore i have to capture ALL output data (standard output, standard error AND CONSOLE).

Looking at the following test batch should make the case more clear:

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

The code is like:

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;
[...]

I am able to capture lines 2+3, but not 4 (used by some programs).
I have also tried powershell (or directly plink) instead of cmd.exe as starting point, but same result.

Is there any way in c# to capture the console out as well or do you know any third party command line being able to redirect CON out to stdout or something like this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

丘比特射中我 2025-01-04 05:19:03

我不确定这是否可能——至少不使用一些简单的 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$ 句柄)的消息。 )。我想这与尝试将进程写入某个文件的输出重定向相同,这(通常)也是不可能的。

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

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

I'm not sure that is even possible - well at least not using some plain simple API.

Please note that I have not found (although I tried) any information on the web that directly confirms that, but here is how I come to this conclusion.

The console in Windows is its own subsystem, managed by csrss.exe (and starting with Windows Vista also conhost.exe, but I digress). It has it's own set APIs (AttachConsole, WriteConsole, etc.) and you can only have one "console" per process.

CMD.EXE on the other hand is just another console mode application, that just happens to use the console and being launched it a console window. You can observe this effect, by launching a different console mode application and watch the process tree in e.g. Process Explorer: there is no CMD.EXE parent process (but rather it is Explorer or whatever you used to start it - including of course CMD.EXE).

Thus far I was trying to show the difference between "the console" and CMD.EXE, batch files, or console mode applications in general.

So when in CMD.EXE you use > CON you are actually causing the same effect as doing a write to CONOUT$ in native applications (or your typical write to /dev/console on a UNIX-like OS). There doesn't seem to be a direct equivalent for managed code, as Console.Out and Console.Error equal stdout and stderr in native applications (or 1 and 2 as file descriptors in CMD.EXE).

Having all that said, when you start a process you're only enabled to redirect it's standard output and standard error streams, but not (per se) the messages it writes to the console (or CONOUT$ handle). I guess that would be the same as trying to redirect output that a process writes to some file, which is also not (generically) possible.

You could possible achieve this using some hooking or injecting something inside the child process to grab the console output.

Being not able to easily do this, is also (one of) the reason(s) why writing a complete terminal (i.e. console window, not CMD.EXE!) replacement for Windows is not easily possible and requires some hacks or workarounds.

苹果你个爱泡泡 2025-01-04 05:19:03

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

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

使用库的主要优点是您可以更好地控制 SSH会议比你能曾经通过一些重定向控制台实现,并且更容易实现...

更新 - 根据评论:

要从远程运行的程序获取所有输出,您需要使用一个带有“交互式”的库/terminal” SSH 类 - 例如 http://www.rebex.net 上的类/ssh-pack/default.aspx带有这样一个类并且工作得很好(没有附属关系,只是一个满意的客户),它可以用作仅代码组件或可视控件(无论适合您的需求)。

AFAIK know what you want (redirecting CON) is only possible by hooking/injecting which is rather complex and basically not necessary to do SSH.

For SSH you can use any number of C# libraries out there (free and commercial):

The main advantage of using a library is that you have much greater control over the SSH session than you could ever achieve via some redirected console AND it is much easier to implement...

UPDATE - as per comments:

To get all output from the remotely running program you need to use a library which comes with an "interactive/terminal" class for SSH - for example the one at http://www.rebex.net/ssh-pack/default.aspx comes with such a class and works really fine (not affilliated, just a happy customer), it can be used as a code-only component or as a visual control (whatever suits your needs).

灰色世界里的红玫瑰 2025-01-04 05:19:03

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

通用控制台重定向器

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

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

Here are some CodeProject projects which do this (via native code), which AFAICT better handle redirecting all console output:

Universal Console Redirector

Redirecting an arbitrary Console's Input/Output

Also, the command freopen allows a program to redirect its streams. However, if a program does an explicit WriteConsole() I'm not sure if it is possible to redirect that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文