Estoy tratando de ejecutar un archivo por lotes en C #, pero no tengo 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 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?
c#
batch-file
process
processstartinfo
Wessel T.
fuente
fuente
command
es. Si contiene rutas con espacios, deberá poner comillas a su alrededor.Respuestas:
Esto debería funcionar. Podría intentar volcar el contenido de las secuencias de salida y error para saber qué está sucediendo:
* EDITAR *
Dada la información adicional en su comentario a continuación, pude recrear el problema. Parece que hay una configuración de seguridad que resulta en este comportamiento (no lo he investigado en detalle).
Esto hace el trabajo 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 archivos por lotes personalizados o ejecutables en el directorio de Windows es una mala práctica de todos modos.* EDIT 2 * Se resulta que si las corrientes se leen de forma sincrónica, se puede producir un callejón sin salida, ya sea mediante la lectura de forma sincronizada antes
WaitForExit
o mediante la lectura de ambosstderr
ystdout
de forma sincronizada uno tras otro.Esto no debería suceder si se utilizan métodos de lectura asíncronos, como en el siguiente ejemplo:
fuente
Esta línea simple ejecutará el archivo por lotes.
fuente
Después de una gran ayuda de Steinar, esto es lo que funcionó para mí:
fuente
~%dp0
. Añadiendo elProcessInfo.WorkingDirectory
arreglado.command
si llama directamente al archivo BAT?command
parámetros podrían usarse para enviar argumentos al archivo BAT, eso no es lo que muestra el código aquí. De hecho, no se usa en absoluto. Y si lo fuera, probablemente debería nombrarsearguments
en su lugar.command
se usa ennew ProcessStartInfo
llamadas.Funciona bien. Lo probé así:
Comenté apagando la ventana para poder verla correr.
fuente
Aquí hay un código de muestra c # que envía 2 parámetros a un archivo bat / cmd para responder esta pregunta .
Comentario: ¿cómo puedo pasar parámetros y leer un resultado de la ejecución del comando?
/ por @Janatbek Sharsheyev
fuente
El siguiente código funcionó bien para mí
fuente
fuente
¿Has intentado iniciarlo como administrador? Inicie Visual Studio como administrador si lo usa, porque trabajar con
.bat
archivos requiere esos privilegios.fuente
Quería algo que fuera más directamente utilizable sin valores de cadena codificados específicos de la organización. Ofrezco lo siguiente como un fragmento de código directamente reutilizable. La desventaja menor es determinar y pasar la carpeta de trabajo al hacer la llamada.
Llamado así:
En este ejemplo, desde Visual Studio 2017, como parte de una ejecución de prueba, quiero ejecutar un archivo por lotes de restablecimiento del entorno antes de ejecutar algunas pruebas. (SpecFlow + xUnit). Me cansé de los pasos adicionales para ejecutar manualmente el archivo bat por separado, y solo quería ejecutar el archivo bat como parte del código de configuración de prueba de C #. El archivo por lotes de reinicio del entorno mueve los archivos de casos de prueba nuevamente a la carpeta de entrada, limpia las carpetas de salida, etc. El método QuotesAround simplemente pone comillas alrededor de la línea de comando en caso de que haya espacios en los nombres de las carpetas ("Archivos de programa", ¿alguien?). Todo lo que contiene es esto: cadena privada QuotesAround (entrada de cadena) {return "\" "+ input +" \ "";}
Espero que algunos encuentren esto útil y ahorren unos minutos si su escenario es similar al mío.
fuente
Con las soluciones propuestas anteriormente, he tenido problemas para ejecutar múltiples comandos npm en un bucle y obtener todas las salidas en la ventana de la consola.
Finalmente comenzó a funcionar después de haber combinado todo de los comentarios anteriores, pero reorganicé el flujo de ejecución del código.
Lo que he notado es que la suscripción de eventos se realizó demasiado tarde (después de que el proceso ya comenzó) y, por lo tanto, algunas salidas no se capturaron.
El siguiente código ahora hace lo siguiente:
El código ha sido probado contra los puntos muertos, aunque es sincrónico (ejecución de un proceso en ese momento), por lo que no puedo garantizar lo que sucedería si se ejecutara en paralelo.
fuente
Usando CliWrap :
fuente
System.Diagnostics.Process.Start(BatchFileName, Parameters);
Sé que esto funcionará para archivos y parámetros por lotes, pero no tengo idea de cómo obtener los resultados en C #. Por lo general, las salidas se definen en el archivo por lotes.
fuente