Ejecutar archivo por lotes en C#
Estoy intentando ejecutar un archivo por lotes en C#, pero no tengo suerte al hacerlo.
He encontrado varios ejemplos en Internet que lo hacen, pero no me funciona.
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 debe 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ías intentar desechar el contenido de los flujos de salida y de error para descubrir 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");
}
* EDITAR *
Dada la información adicional en su comentario a continuación, pude recrear el problema. Parece haber alguna configuración de seguridad que da como resultado este comportamiento (no lo he investigado en detalle).
Esto funciona si el archivo por lotes no se encuentra en formato C:\Windows\System32
. Intente moverlo a otra ubicación, por ejemplo, la ubicación de su ejecutable. Tenga en cuenta que mantener archivos por lotes o ejecutables personalizados en el directorio de Windows es una mala práctica de todos modos.
*EDITAR 2*
Resulta que si los flujos se leen sincrónicamente, puede ocurrir un punto muerto, ya sea leyendo sincrónicamente antes o leyendo ambos y sincrónicamente uno después del otro.WaitForExit
stderr
stdout
Esto no debería suceder si se utilizan métodos de lectura asincrónicos, 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.