Ejecutar archivo por lotes en C #

Estoy tratando de ejecutar un archivo por lotes en C #, pero no estoy teniendo suerte al hacerlo.

He encontrado varios ejemplos en Internet haciéndolo, pero no funciona para mí.

public void ExecuteCommand(string command) { int ExitCode; ProcessStartInfo ProcessInfo; Process Process; ProcessInfo = new ProcessStartInfo("cmd.exe", "/c " + command); ProcessInfo.CreateNoWindow = true; ProcessInfo.UseShellExecute = false; Process = Process.Start(ProcessInfo); Process.WaitForExit(); ExitCode = Process.ExitCode; Process.Close(); MessageBox.Show("ExitCode: " + ExitCode.ToString(), "ExecuteCommand"); } 

La cadena de comando contiene el nombre del archivo por lotes (almacenado en system32 ) y algunos archivos que debería manipular. (Ejemplo: txtmanipulator file1.txt file2.txt file3.txt ). Cuando ejecuto el archivo por lotes manualmente, funciona correctamente.

Al ejecutar el código, me da un **ExitCode: 1** (Catch all for general errors)

¿Qué estoy haciendo mal?

Esto debería funcionar. Podría tratar de eliminar los contenidos de la salida y las secuencias de error para averiguar qué está sucediendo:

 static void ExecuteCommand(string command) { int exitCode; ProcessStartInfo processInfo; Process process; processInfo = new ProcessStartInfo("cmd.exe", "/c " + command); processInfo.CreateNoWindow = true; processInfo.UseShellExecute = false; // *** Redirect the output *** processInfo.RedirectStandardError = true; processInfo.RedirectStandardOutput = true; process = Process.Start(processInfo); process.WaitForExit(); // *** Read the streams *** // Warning: This approach can lead to deadlocks, see Edit #2 string output = process.StandardOutput.ReadToEnd(); string error = process.StandardError.ReadToEnd(); exitCode = process.ExitCode; Console.WriteLine("output>>" + (String.IsNullOrEmpty(output) ? "(none)" : output)); Console.WriteLine("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error)); Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand"); process.Close(); } static void Main() { ExecuteCommand("echo testing"); } 

* EDIT *

Dada la información adicional en su comentario a continuación, pude recrear el problema. Parece que hay alguna configuración de seguridad que da como resultado este comportamiento (no se ha investigado eso en detalle).

Esto funciona si el archivo por lotes no se encuentra en C:\Windows\System32 . Intente moverlo a otra ubicación, por ejemplo, la ubicación de su ejecutable. Tenga en cuenta que mantener los archivos por lotes personalizados o ejecutables en el directorio de Windows es una mala práctica de todos modos.

* EDIT 2 * Resulta que si las secuencias se leen de forma síncrona, puede producirse un interlocking, ya sea leyendo de forma síncrona antes de WaitForExit o leyendo stderr y stdout síncrona uno tras otro.

Esto no debería ocurrir si se usan los métodos de lectura asíncrona, como en el siguiente ejemplo:

 static void ExecuteCommand(string command) { var processInfo = new ProcessStartInfo("cmd.exe", "/c " + command); processInfo.CreateNoWindow = true; processInfo.UseShellExecute = false; processInfo.RedirectStandardError = true; processInfo.RedirectStandardOutput = true; var process = Process.Start(processInfo); process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => Console.WriteLine("output>>" + e.Data); process.BeginOutputReadLine(); process.ErrorDataReceived += (object sender, DataReceivedEventArgs e) => Console.WriteLine("error>>" + e.Data); process.BeginErrorReadLine(); process.WaitForExit(); Console.WriteLine("ExitCode: {0}", process.ExitCode); process.Close(); } 
 System.Diagnostics.Process.Start("c:\\batchfilename.bat"); 

esta simple línea ejecutará el archivo por lotes.

Después de una gran ayuda de Steinar esto es lo que funcionó para mí:

 public void ExecuteCommand(string command) { int ExitCode; ProcessStartInfo ProcessInfo; Process process; ProcessInfo = new ProcessStartInfo(Application.StartupPath + "\\txtmanipulator\\txtmanipulator.bat", command); ProcessInfo.CreateNoWindow = true; ProcessInfo.UseShellExecute = false; ProcessInfo.WorkingDirectory = Application.StartupPath + "\\txtmanipulator"; // *** Redirect the output *** ProcessInfo.RedirectStandardError = true; ProcessInfo.RedirectStandardOutput = true; process = Process.Start(ProcessInfo); process.WaitForExit(); // *** Read the streams *** string output = process.StandardOutput.ReadToEnd(); string error = process.StandardError.ReadToEnd(); ExitCode = process.ExitCode; MessageBox.Show("output>>" + (String.IsNullOrEmpty(output) ? "(none)" : output)); MessageBox.Show("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error)); MessageBox.Show("ExitCode: " + ExitCode.ToString(), "ExecuteCommand"); process.Close(); } 

Funciona bien. Lo probé así:

 String command = @"C:\Doit.bat"; ProcessInfo = new ProcessStartInfo("cmd.exe", "/c " + command); // ProcessInfo.CreateNoWindow = true; 

Comenté apagar la ventana para poder VERLO correr.

El siguiente código funcionó bien para mí

 using System.Diagnostics; public void ExecuteBatFile() { Process proc = null; string _batDir = string.Format(@"C:\"); proc = new Process(); proc.StartInfo.WorkingDirectory = _batDir; proc.StartInfo.FileName = "myfile.bat"; proc.StartInfo.CreateNoWindow = false; proc.Start(); proc.WaitForExit(); ExitCode = proc.ExitCode; proc.Close(); MessageBox.Show("Bat file executed..."); } 
 using System.Diagnostics; private void ExecuteBatFile() { Process proc = null; try { string targetDir = string.Format(@"D:\mydir"); //this is where mybatch.bat lies proc = new Process(); proc.StartInfo.WorkingDirectory = targetDir; proc.StartInfo.FileName = "lorenzo.bat"; proc.StartInfo.Arguments = string.Format("10"); //this is argument proc.StartInfo.CreateNoWindow = false; proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; //this is for hiding the cmd window...so execution will happen in back ground. proc.Start(); proc.WaitForExit(); } catch (Exception ex) { Console.WriteLine("Exception Occurred :{0},{1}", ex.Message, ex.StackTrace.ToString()); } } 

¿Has intentado iniciarlo como administrador? Inicie Visual Studio como administrador si lo usa, porque trabajar con archivos .bat requiere esos privilegios.