puntos para linea entrada consola comandos comando argumentos c# command-line

para - Cómo: Ejecutar la línea de comandos en C#, obtener resultados STD OUT



main c# (13)

¿Cómo ejecuto un programa de línea de comandos desde C # y recupero los resultados de STD OUT? Específicamente, quiero ejecutar DIFF en dos archivos que se seleccionan mediante programación y escribir los resultados en un cuadro de texto. Sí, podría resolver esto por mí mismo, pero seguramente alguien más ha hecho algo así y soy perezosa ...


Aquí hay una muestra rápida:

//Create process System.Diagnostics.Process pProcess = new System.Diagnostics.Process(); //strCommand is path and file name of command to run pProcess.StartInfo.FileName = strCommand; //strCommandParameters are parameters to pass to program pProcess.StartInfo.Arguments = strCommandParameters; pProcess.StartInfo.UseShellExecute = false; //Set output of program to be written to process output stream pProcess.StartInfo.RedirectStandardOutput = true; //Optional pProcess.StartInfo.WorkingDirectory = strWorkingDirectory; //Start the process pProcess.Start(); //Get program output string strOutput = pProcess.StandardOutput.ReadToEnd(); //Wait for process to finish pProcess.WaitForExit();


Deberá usar ProcessStartInfo con RedirectStandardOutput habilitado; luego podrá leer la secuencia de salida. Es posible que le resulte más fácil usar ">" para redirigir la salida a un archivo (a través del sistema operativo) y luego simplemente leer el archivo.

[editar: como lo que hizo Ray: +1]


Esto puede ser útil para alguien si intenta consultar la memoria caché local de ARP en una PC / servidor.

List<string[]> results = new List<string[]>(); using (Process p = new Process()) { p.StartInfo.CreateNoWindow = true; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.UseShellExecute = false; p.StartInfo.Arguments = "/c arp -a"; p.StartInfo.FileName = @"C:/Windows/System32/cmd.exe"; p.Start(); string line; while ((line = p.StandardOutput.ReadLine()) != null) { if (line != "" && !line.Contains("Interface") && !line.Contains("Physical Address")) { var lineArr = line.Trim().Split('' '').Select(n => n).Where(n => !string.IsNullOrEmpty(n)).ToArray(); var arrResult = new string[] { lineArr[0], lineArr[1], lineArr[2] }; results.Add(arrResult); } } p.WaitForExit(); }


Hay otro parámetro que encontré útil, que uso para eliminar la ventana de proceso

pProcess.StartInfo.CreateNoWindow = true;

esto ayuda a ocultar por completo la ventana de la consola negra del usuario, si eso es lo que desea.


Hay una clase de ProcessHelper en Código de código abierto de dominio público que podría interesarle.


La respuesta aceptada en esta página tiene una debilidad que es problemática en situaciones excepcionales. Hay dos manejadores de archivos en los que los programas escriben por convención, stdout y stderr. Si acaba de leer un solo identificador de archivo, como la respuesta de Ray, y el programa que está iniciando escribe suficiente salida a stderr, llenará el búfer y el bloque de stderr de salida. Entonces sus dos procesos están bloqueados. El tamaño del búfer puede ser 4K. Esto es extremadamente raro en los programas de corta duración, pero si tiene un programa de ejecución larga que se ejecuta repetidamente en stderr, eventualmente sucederá. Esto es difícil de depurar y localizar.

Hay un par de buenas maneras de lidiar con esto.

  1. Una forma es ejecutar cmd.exe en lugar de su programa y usar el argumento / c para cmd.exe para invocar su programa junto con el argumento "2> & 1" para cmd.exe para indicarle que combine stdout y stderr.

    var p = new Process(); p.StartInfo.FileName = "cmd.exe"; p.StartInfo.Arguments = "/c mycmd.exe 2>&1";

  2. Otra forma es usar un modelo de programación que lea ambos manejadores al mismo tiempo.

    var p = new Process(); p.StartInfo.FileName = "cmd.exe"; p.StartInfo.Arguments = @"/c dir /windows"; p.StartInfo.CreateNoWindow = true; p.StartInfo.RedirectStandardError = true; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.RedirectStandardInput = false; p.OutputDataReceived += (a, b) => Console.WriteLine(b.Data); p.ErrorDataReceived += (a, b) => Console.WriteLine(b.Data); p.Start(); p.BeginErrorReadLine(); p.BeginOutputReadLine(); p.WaitForExit();


Puede iniciar cualquier programa de línea de comandos usando la clase de proceso y configurar la propiedad StandardOutput de la instancia de proceso con un lector de flujo que cree (ya sea en base a una cadena o una ubicación de memoria). Una vez que se completa el proceso, puedes hacer lo que necesites en esa secuencia.


Puede que esta no sea la forma mejor / más fácil, pero puede ser una opción:

Cuando ejecute desde su código, agregue "> output.txt" y luego lea el archivo output.txt.


Si no le importa introducir una dependencia, CliWrap puede simplificar esto para usted:

var cli = new Cli("target.exe"); var output = await cli.ExecuteAsync("arguments", "stdin"); var stdout = output.StandardOutput;


Solo por diversión, aquí está mi solución completa para obtener la salida de PYTHON, con solo hacer clic en un botón, con informes de errores. Solo agregue un botón llamado "butPython" y una etiqueta llamada "llHello" ...

private void butPython(object sender, EventArgs e) { llHello.Text = "Calling Python..."; this.Refresh(); Tuple<String,String> python = GoPython(@"C:/Users/BLAH/Desktop/Code/Python/BLAH.py"); llHello.Text = python.Item1; // Show result. if (python.Item2.Length > 0) MessageBox.Show("Sorry, there was an error:" + Environment.NewLine + python.Item2); } public Tuple<String,String> GoPython(string pythonFile, string moreArgs = "") { ProcessStartInfo PSI = new ProcessStartInfo(); PSI.FileName = "py.exe"; PSI.Arguments = string.Format("/"{0}/" {1}", pythonFile, moreArgs); PSI.CreateNoWindow = true; PSI.UseShellExecute = false; PSI.RedirectStandardError = true; PSI.RedirectStandardOutput = true; using (Process process = Process.Start(PSI)) using (StreamReader reader = process.StandardOutput) { string stderr = process.StandardError.ReadToEnd(); // Error(s)!! string result = reader.ReadToEnd(); // What we want. return new Tuple<String,String> (result,stderr); } }


System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(@"program_to_call.exe"); psi.RedirectStandardOutput = true; psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; psi.UseShellExecute = false; System.Diagnostics.Process proc System.Diagnostics.Process.Start(psi);; System.IO.StreamReader myOutput = proc.StandardOutput; proc.WaitForExit(2000); if (proc.HasExited) { string output = myOutput.ReadToEnd(); }


// Start the child process. Process p = new Process(); // Redirect the output stream of the child process. p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; p.StartInfo.FileName = "YOURBATCHFILE.bat"; p.Start(); // Do not wait for the child process to exit before // reading to the end of its redirected stream. // p.WaitForExit(); // Read the output stream first and then wait. string output = p.StandardOutput.ReadToEnd(); p.WaitForExit();

El código es de MSDN .


// usage const string ToolFileName = "example.exe"; string output = RunExternalExe(ToolFileName); public string RunExternalExe(string filename, string arguments = null) { var process = new Process(); process.StartInfo.FileName = filename; if (!string.IsNullOrEmpty(arguments)) { process.StartInfo.Arguments = arguments; } process.StartInfo.CreateNoWindow = true; process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; process.StartInfo.UseShellExecute = false; process.StartInfo.RedirectStandardError = true; process.StartInfo.RedirectStandardOutput = true; var stdOutput = new StringBuilder(); process.OutputDataReceived += (sender, args) => stdOutput.AppendLine(args.Data); // Use AppendLine rather than Append since args.Data is one line of output, not including the newline character. string stdError = null; try { process.Start(); process.BeginOutputReadLine(); stdError = process.StandardError.ReadToEnd(); process.WaitForExit(); } catch (Exception e) { throw new Exception("OS error while executing " + Format(filename, arguments)+ ": " + e.Message, e); } if (process.ExitCode == 0) { return stdOutput.ToString(); } else { var message = new StringBuilder(); if (!string.IsNullOrEmpty(stdError)) { message.AppendLine(stdError); } if (stdOutput.Length != 0) { message.AppendLine("Std output:"); message.AppendLine(stdOutput.ToString()); } throw new Exception(Format(filename, arguments) + " finished with exit code = " + process.ExitCode + ": " + message); } } private string Format(string filename, string arguments) { return "''" + filename + ((string.IsNullOrEmpty(arguments)) ? string.Empty : " " + arguments) + "''"; }