Capture ALL (stdout, stderr AND CON) cmd output performing plink with C # (std out + err ok, CON does not work)

I want to open SSH connections from C # by opening a process and running plink. All products must be assembled and, depending on the results, the program will run actions in ssh. My big problem is that I use a couple if different scenarios and I need (automatic) user interaction. So I have to capture ALL the output (standard output, standard error AND CONSOLE).

A look at the following test batch should make the situation clearer:

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

The code looks like this:

 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 can capture lines 2 + 3, but not 4 (used by some programs). I also tried powershell (or directly plink) instead of cmd.exe as a starting point, but the same result.

Is there any way in C # to capture the console, or do you know that any third-party command line can redirect CON out to stdout or something like this?

+7
source share
3 answers

AFAIK knows what you want (redirecting CON) is only possible when connecting / injecting, which is quite complicated and basically does not need to do SSH.

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

The main advantage of using the library is that you have much more control over your SSH session than you could have achieved through some sort of redirected console. And it is much easier to implement ...

UPDATE - according to comments:

To get all the output from a remote program, you need to use the library that comes with the "interactive / terminal" class for SSH - for example, http://www.rebex.net/ssh-pack/default.aspx comes with that class and It works very well (not attached, just a happy client), it can be used as a component of the code or as a visual control (regardless of your needs).

+3
source

I'm not sure if this is possible - well, at least not using a simple simple API.

Please note that I did not find (although I tried) any information on the Internet, which directly confirms , but here is how I came to this conclusion.

The Windows console is its own subsystem managed by csrss.exe (and also starting with Windows Vista conhost.exe , but I'm distracted). It has its own APIs ( AttachConsole , WriteConsole , etc.), and you can only have one β€œconsole” for each process.

CMD.EXE on the other hand, is just another console application that just uses the console and launches a console window. You can observe this effect by running another application in console mode and look at the process tree, for example. Process Explorer: the parent process CMD.EXE is missing (but rather, it is Explorer or everything that you used to start it, including, of course, CMD.EXE).

So far I have tried to show the difference between the "console" and CMD.EXE , batch files or applications in console mode as a whole.

Therefore, when you use > CON in CMD.EXE , you actually cause the same effect as writing to CONOUT$ in your own applications (or your typical entry in /dev/console on a UNIX-like OS). There seems to be no direct equivalent for managed code, since Console.Out and Console.Error are equal to stdout and stderr in native applications (or 1 and 2 as file descriptors in CMD.EXE )).

With all that, when you start a process, you can redirect its standard output and standard error streams, but not (as such) messages that it writes to the console (or CONOUT$ descriptor). I assume that this will be the same as an attempt to redirect the output that the process writes to some file, which is also impossible (in general) possible.

You could achieve this using some kind of binding or injection of something inside the child process to capture the console output.

This cannot be done easily, is also (one of) the reason why replacing a full terminal (for example, a console window, not CMD.EXE !) For Windows is not always possible and requires some hacks or workarounds.

+7
source

Here are some CodeProject projects that do this (through native code) that AFAICT handles better by redirecting all console output:

Universal console redirector

Console arbitrary I / O redirection

In addition, the freopen command allows the program to redirect its threads. However, if the program executes an explicit WriteConsole (), I'm not sure if this can be redirected.

0
source

All Articles