¿Cómo invoco una aplicación de consola desde mi aplicación .NET y capturo toda la salida generada en la consola?
(Recuerde, no quiero guardar la información primero en un archivo y luego volver a enumerarla, ya que me encantaría recibirla en vivo).
¿Cómo invoco una aplicación de consola desde mi aplicación .NET y capturo toda la salida generada en la consola?
(Recuerde, no quiero guardar la información primero en un archivo y luego volver a enumerarla, ya que me encantaría recibirla en vivo).
Respuestas:
Esto se puede lograr fácilmente usando la propiedad ProcessStartInfo.RedirectStandardOutput . Una muestra completa está contenida en la documentación de MSDN vinculada; La única advertencia es que es posible que también deba redirigir la secuencia de error estándar para ver todos los resultados de su aplicación.
Process compiler = new Process();
compiler.StartInfo.FileName = "csc.exe";
compiler.StartInfo.Arguments = "/r:System.dll /out:sample.exe stdstr.cs";
compiler.StartInfo.UseShellExecute = false;
compiler.StartInfo.RedirectStandardOutput = true;
compiler.Start();
Console.WriteLine(compiler.StandardOutput.ReadToEnd());
compiler.WaitForExit();
Console.Write
úsala.
Esta es una pequeña mejora sobre la respuesta aceptada de @mdb . Específicamente, también capturamos la salida de error del proceso. Además, capturamos estas salidas a través de eventos, ya ReadToEnd()
no funciona si desea capturar tanto error y salida normal. Me tomó un tiempo hacer que esto funcione porque en realidad también requiere BeginxxxReadLine()
llamadas después Start()
.
Manera asincrónica:
using System.Diagnostics;
Process process = new Process();
void LaunchProcess()
{
process.EnableRaisingEvents = true;
process.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_OutputDataReceived);
process.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_ErrorDataReceived);
process.Exited += new System.EventHandler(process_Exited);
process.StartInfo.FileName = "some.exe";
process.StartInfo.Arguments = "param1 param2";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardOutput = true;
process.Start();
process.BeginErrorReadLine();
process.BeginOutputReadLine();
//below line is optional if we want a blocking call
//process.WaitForExit();
}
void process_Exited(object sender, EventArgs e)
{
Console.WriteLine(string.Format("process exited with code {0}\n", process.ExitCode.ToString()));
}
void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(e.Data + "\n");
}
void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
Console.WriteLine(e.Data + "\n");
}
Use ProcessInfo.RedirectStandardOutput para redirigir la salida al crear su proceso de consola.
Luego puede usar Process.StandardOutput para leer la salida del programa.
El segundo enlace tiene un código de muestra de cómo hacerlo.
ConsoleAppLauncher es una biblioteca de código abierto creada específicamente para responder esa pregunta. Captura todos los resultados generados en la consola y proporciona una interfaz simple para iniciar y cerrar la aplicación de la consola.
El evento ConsoleOutput se activa cada vez que la consola escribe una nueva línea en la salida estándar / de error. Las líneas se ponen en cola y se garantiza que sigan el orden de salida.
También disponible como paquete NuGet .
Llamada de muestra para obtener la salida completa de la consola:
// Run simplest shell command and return its output.
public static string GetWindowsVersion()
{
return ConsoleApp.Run("cmd", "/c ver").Output.Trim();
}
Muestra con comentarios en vivo:
// Run ping.exe asynchronously and return roundtrip times back to the caller in a callback
public static void PingUrl(string url, Action<string> replyHandler)
{
var regex = new Regex("(time=|Average = )(?<time>.*?ms)", RegexOptions.Compiled);
var app = new ConsoleApp("ping", url);
app.ConsoleOutput += (o, args) =>
{
var match = regex.Match(args.Line);
if (match.Success)
{
var roundtripTime = match.Groups["time"].Value;
replyHandler(roundtripTime);
}
};
app.Run();
}
Agregué varios métodos auxiliares a la Plataforma O2 (proyecto de código abierto) que le permiten crear fácilmente una interacción con otro proceso a través de la salida y entrada de la consola (consulte http://code.google.com/p/o2platform/ source / browse / trunk / O2_Scripts / APIs / Windows / CmdExe / CmdExeAPI.cs )
También puede ser útil para usted la API que permite ver el resultado de la consola del proceso actual (en un control existente o ventana emergente). Consulte esta publicación de blog para obtener más detalles: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (este blog también contiene detalles sobre cómo consumir la salida de la consola de nuevos procesos)
Hice una versión reactiva que acepta devoluciones de llamada para stdOut y StdErr.
onStdOut
y onStdErr
se llaman de forma asíncrona,
tan pronto como llegan los datos (antes de que salga el proceso).
public static Int32 RunProcess(String path,
String args,
Action<String> onStdOut = null,
Action<String> onStdErr = null)
{
var readStdOut = onStdOut != null;
var readStdErr = onStdErr != null;
var process = new Process
{
StartInfo =
{
FileName = path,
Arguments = args,
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = readStdOut,
RedirectStandardError = readStdErr,
}
};
process.Start();
if (readStdOut) Task.Run(() => ReadStream(process.StandardOutput, onStdOut));
if (readStdErr) Task.Run(() => ReadStream(process.StandardError, onStdErr));
process.WaitForExit();
return process.ExitCode;
}
private static void ReadStream(TextReader textReader, Action<String> callback)
{
while (true)
{
var line = textReader.ReadLine();
if (line == null)
break;
callback(line);
}
}
A continuación se ejecutará executable
con args
e imprimir
a la consola
RunProcess(
executable,
args,
s => { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(s); },
s => { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(s); }
);
Desde PythonTR - Python Programcıları Derneği, e-kitap, örnek :
Process p = new Process(); // Create new object
p.StartInfo.UseShellExecute = false; // Do not use shell
p.StartInfo.RedirectStandardOutput = true; // Redirect output
p.StartInfo.FileName = "c:\\python26\\python.exe"; // Path of our Python compiler
p.StartInfo.Arguments = "c:\\python26\\Hello_C_Python.py"; // Path of the .py to be executed
Añadido process.StartInfo.**CreateNoWindow** = true;
y timeout
.
private static void CaptureConsoleAppOutput(string exeName, string arguments, int timeoutMilliseconds, out int exitCode, out string output)
{
using (Process process = new Process())
{
process.StartInfo.FileName = exeName;
process.StartInfo.Arguments = arguments;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.CreateNoWindow = true;
process.Start();
output = process.StandardOutput.ReadToEnd();
bool exited = process.WaitForExit(timeoutMilliseconds);
if (exited)
{
exitCode = process.ExitCode;
}
else
{
exitCode = -1;
}
}
}
StandardOutput.ReadToEnd()
, no volverá a la siguiente declaración hasta el final de la aplicación. ¡así que su tiempo de espera en WaitForExit (timeoutMilliseconds) no funciona! (¡su código se bloqueará!)