2012-01-23 24 views
7

Quiero abrir conexiones SSH desde C# abriendo un proceso y ejecutando plink. Todos los resultados se deben recopilar y, según los resultados, el programa disparará acciones al ssh. Mi gran problema es que estoy usando un par de scripts si diferentes y necesito una interacción del usuario (automatizada). Por lo tanto, tengo que capturar TODOS los datos de salida (salida estándar, error estándar Y CONSOLA).Capturar TODOS (stdout, stderr Y CON) salida de cmd ejecutando plink con C# (salida estándar + errar ok, CON no funciona)

Mirando el siguiente lote de prueba debe hacer el caso más claro:

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

El código es como:

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

soy capaz de capturar las líneas 2 + 3, pero no 4 (utilizado por algunos programas). También probé Powershell (o directamente Plink) en lugar de cmd.exe como punto de partida, pero el mismo resultado.

¿Hay alguna forma en C# para capturar la consola también o sabe usted que alguna línea de comando de terceros puede redirigir CON a stdout o algo como esto?

+0

¿Cuál es la diferencia entre la salida estándar y la consola? –

+1

@DanielHilgarth No estoy del todo seguro para Windows, pero en UNIX la salida estándar iría a cualquier parte (incluso a un archivo), mientras que la otra siempre iría a la consola (modo de texto). Eso se muestra, por ejemplo, si ha iniciado sesión de forma remota. La salida de la consola siempre va a la consola/computadora física (creo que hay algunas opciones para cambiar esto también, pero en términos generales). –

Respuesta

3

AFAIK saber lo que quiere (redirigir CON) solo es posible mediante el enganche/inyección que es bastante complejo y básicamente no es necesario para hacer SSH.

Para SSH se puede utilizar cualquier número de C# bibliotecas por ahí (comercial libre y):

La principal ventaja de utilizar una biblioteca es que tiene mucho mayor control sobre la sesión SSH lo que nunca podría lograr a través de algún consola redirigida y es mucho más fácil de implementar ...

ACTUALIZACIÓN - según comentarios:

Para obtener toda la salida del programa que se ejecuta remotamente, necesita usar una biblioteca que viene con una clase "interactiva/terminal" para SSH; por ejemplo, la de http://www.rebex.net/ssh-pack/default.aspx viene con una clase así y funciona realmente bien (no afiliado, solo un cliente feliz), se puede usar como un componente de solo código o como un control visual (lo que se ajuste a sus necesidades).

+1

+1 "más fácil de implementar ..." y probablemente también más robusto. –

+0

Ya probé SharpSSH, pero también solo admitía std y err out, no consola. Probará sshnet, pero no realmente optimisitc (le dirá los resultados más adelante). "no es necesario" depende de las cosas necesarias.Necesito un programa para automatizar la interacción del usuario en programas con consola "gui" y esto solo se escribe en la pantalla y no en las transmisiones. –

+0

@Yahia: Necesito que la salida del programa se ejecute de forma remota. Al final, significa que necesito el mismo resultado que usar plink en un prompt cmd.exe ("lo que veo en windows") y luego interactuar en esta sesión ssh –

7

No estoy seguro de que sea posible, al menos no usando una API sencilla.

Tenga en cuenta que no he encontrado (aunque he intentado) cualquier información en la web que confirma directamente eso, pero aquí es cómo he llegado a esta conclusión.

La consola en Windows es su propio subsistema, administrado por csrss.exe (y comenzando con Windows Vista también conhost.exe, pero estoy divagando). Tiene su propio conjunto de API (AttachConsole, WriteConsole, etc.) y solo puede tener una "consola" por proceso.

CMD.EXE por el contrario, es simplemente otra aplicación de modo de consola, que simplemente utiliza la consola y se inicia una ventana de consola. Puede observar este efecto, iniciando una aplicación de modo de consola diferente y observando el árbol de proceso en, p. Ej. Process Explorer: no hay un proceso padre CMD.EXE (sino que es Explorer o lo que sea que usaste para iniciarlo, incluido, por supuesto, CMD.EXE).

Hasta ahora estaba tratando de mostrar la diferencia entre "la consola" y CMD.EXE, archivos de proceso por lotes o aplicaciones en modo consola en general.

Por eso, cuando en CMD.EXE utiliza > CON en realidad se está causando el mismo efecto que hacer una escritura en CONOUT$ en aplicaciones nativas (o su escritura típica a /dev/console en un sistema operativo UNIX). No parece haber un equivalente directo para el código administrado, como Console.Out y Console.Error igual a stdout y stderr en aplicaciones nativas (o 1 y 2 como descriptores de archivos en CMD.EXE).

Dicho todo esto, cuando inicia un proceso solo puede redirigir su salida estándar y las secuencias de error estándar, pero no (per se) los mensajes que escribe en la consola (o el identificador CONOUT$). Supongo que eso sería lo mismo que tratar de redirigir el resultado que un proceso escribe en algún archivo, que tampoco es (genéricamente) posible.

Puede lograrlo utilizando un enganche o inyectando algo dentro del proceso hijo para capturar la salida de la consola.

Al no ser capaz de hacer esto fácilmente, también es una de las razones por las cuales escribir un terminal completo (es decir, ventana de la consola, no CMD.EXE!) Es difícil de reemplazar y requiere algunos hacks o soluciones .

0

Éstos son algunos proyectos CodeProject la que hacen esto (a través de código nativo), que AFAICT mejor manejo redireccionar toda la salida de la consola:

Universal Console Redirector

Redirecting an arbitrary Console's Input/Output

Además, el comando freopen permite que un programa redirigir sus flujos. Sin embargo, si un programa tiene una WriteConsole explícita() no estoy seguro de si es posible redirigir eso.

+1

Estos programas también muestran solo el estándar y error, pero no la consola –

+0

Puede intentar usar freopen para redirigir CONOUT; ver http://stackoverflow.com/questions/311955/redirecting-cout-to-a-console-in- windows –

Cuestiones relacionadas