Capture TODAS las salidas(stdout, stderr y CON) de cmd ejecutando plink con C#(std out+err ok, CON no funciona)
shell redirect (3)
Quiero abrir conexiones SSH desde c # al abrir un proceso y ejecutar 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 diferentes y necesito interacción de usuario (automatizada). Por lo tanto, tengo que capturar TODOS los datos de salida (salida estándar, error estándar Y CONSOLA).
Ver el siguiente lote de prueba debería aclarar el caso:
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;
[...]
Puedo 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 sabes que una línea de comandos de terceros puede redirigir a CON a stdout o algo como esto?
AFAIK sabe lo que quiere (redireccionando CON) solo es posible enganchando / inyectando que es bastante complejo y básicamente no es necesario para hacer SSH.
Para SSH puede usar cualquier cantidad de bibliotecas de C # disponibles (gratuitas y comerciales):
- http://www.chilkatsoft.com/ssh-sftp-component.asp (comercial)
- http://www.tamirgal.com/blog/page/SharpSSH.aspx (gratis)
- http://sshnet.codeplex.com/ (gratis)
- http://www.rebex.net/ssh-pack/default.aspx (comercial)
- http://www.eldos.com/sbb/desc-ssh.php (comercial)
La principal ventaja de utilizar una biblioteca es que tienes mucho más control sobre la sesión SSH de lo que podrías lograr a través de alguna consola redirigida Y es mucho más fácil de implementar ...
ACTUALIZACIÓN - según los comentarios:
Para obtener todos los resultados del programa que se ejecuta de forma remota, necesita utilizar una biblioteca que viene con una clase "interactiva / terminal" para SSH, por ejemplo, la que se encuentra en http://www.rebex.net/ssh-pack/default.aspx. viene con una clase así y funciona realmente bien (no afiliado, solo un cliente feliz), puede usarse como un componente de solo código o como un control visual (lo que se ajuste a sus necesidades).
Aquí hay algunos proyectos de CodeProject que hacen esto (a través del código nativo), que AFAICT maneja mejor al redirigir todo el resultado de la consola:
Redirigir una entrada / salida de una consola arbitraria
Además, el comando freopen permite que un programa redirija sus flujos. Sin embargo, si un programa tiene una WriteConsole explícita () no estoy seguro de si es posible redirigir eso.
No estoy seguro de que sea posible, bueno al menos no usar alguna API sencilla.
Tenga en cuenta que no he encontrado (aunque lo intenté) ninguna información en la web que lo confirme directamente , pero aquí es cómo llego 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 sus propias API establecidas ( AttachConsole
, WriteConsole
, etc.) y solo puede tener una "consola" por proceso.
CMD.EXE
otro lado, CMD.EXE
es simplemente otra aplicación de modo de consola, que simplemente usa la consola y la lanza a una ventana de consola. Puede observar este efecto, iniciando una aplicación de modo de consola diferente y observando el árbol de procesos en, por ejemplo, Process Explorer: no hay un proceso padre CMD.EXE (sino que es Explorer o lo que sea que usó para iniciarlo, incluido, por supuesto, CMD). EXE).
Hasta ahora, estaba tratando de mostrar la diferencia entre "la consola" y CMD.EXE
, los archivos por lotes o las aplicaciones en modo consola en general.
Entonces, cuando en CMD.EXE
utiliza > CON
, en realidad está causando el mismo efecto que escribir en CONOUT$
en aplicaciones nativas (o su escritura típica en /dev/console
en un sistema operativo tipo UNIX). No parece haber un equivalente directo para el código administrado, ya que Console.Out
y Console.Error
igual a stdout
y stderr
en las aplicaciones nativas (o 1
y 2
como descriptores de archivos en CMD.EXE
).
Habiendo dicho todo esto, cuando comienzas un proceso, solo estás habilitado para redirigir su salida estándar y flujos de error estándar, pero no (per se) los mensajes que escribe en la consola (o CONOUT$
handle). 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.
Posiblemente podrías lograr esto usando algunos enganches o inyectando algo dentro del proceso secundario para capturar la salida de la consola.
No ser capaz de hacer esto fácilmente, también es una de las razones por las cuales escribir un reemplazo completo de terminal (es decir, ventana de consola, no CMD.EXE
!) Para Windows no es fácilmente posible y requiere algunos hacks o soluciones temporales.