c# - studio - El servicio se cuelga en WaitForExit después de llamar al archivo por lotes
windows service visual studio 2015 (8)
Tengo un servicio que a veces llama un archivo por lotes. El archivo por lotes tarda de 5 a 10 segundos en ejecutarse:
System.Diagnostics.Process proc = new System.Diagnostics.Process(); // Declare New Process
proc.StartInfo.FileName = fileName;
proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
proc.StartInfo.CreateNoWindow = true;
proc.Start();
proc.WaitForExit();
El archivo existe y el código funciona cuando ejecuto el mismo código en la consola. Sin embargo, cuando se ejecuta dentro del servicio, se cuelga en WaitForExit()
. Debo matar el archivo por lotes del Proceso para continuar. (Estoy seguro de que el archivo existe, ya que puedo verlo en la lista de procesos).
¿Cómo puedo solucionar este problema?
Actualización # 1:
El código de Kevin me permite obtener resultados. Uno de mis archivos por lotes todavía está colgando.
"C: / EnterpriseDB / Postgres / 8.3 / bin / pg_dump.exe" -i -h localhost -p 5432 -U postgres -F p -a -D -v -f "c: / backupcasecocher / backupdateevent2008.sql" -t "/" public / ". /" dateevent / "" "DbTest"
El otro archivo por lotes es:
"C: / EnterpriseDB / Postgres / 8.3 / bin / vacuumdb.exe" -U postgres -d DbTest
Revisé la ruta y la ruta de postgresql
está bien. El directorio de salida existe y todavía funciona fuera del servicio. ¿Algunas ideas?
Actualización # 2:
En lugar de la ruta del archivo por lotes, escribí el "C: / EnterpriseDB / Postgres / 8.3 / bin / pg_dump.exe" para el proc.StartInfo.FileName
y agregué todos los parámetros a proc.StartInfo.Arguments
. Los resultados no se modifican, pero veo el pg_dump.exe
en la ventana de proceso. De nuevo, esto solo ocurre dentro del servicio.
Actualización # 3:
He ejecutado el servicio con un usuario en el grupo de administradores, en vano. Restaure null
para el nombre de usuario y la contraseña del servicio
Actualización # 4:
Creé un servicio simple para escribir un seguimiento en el registro de eventos y ejecutar un archivo por lotes que contenga "dir" en él. Ahora se bloqueará en proc.Start();
- Intenté cambiar la Cuenta de LocalSystem a Usuario y configuré el usuario y la contraseña del administrador, todavía nada.
El siguiente paso que tomaré es encender el depurador y ver si puede decir qué espera el programa. Si se le expiere en la depuración en el ensamblado, es posible que pueda obtener una IDEA de lo que está sucediendo utilizando herramientas como ProcExp, FileMon, etc.
Ser un SERVICIO de Windows, y no un servicio web, hace una gran diferencia. De todos modos, ¿has probado mi sugerencia de configurar el "Permitir que el servicio interactúe con el escritorio"?
Si está desesperado, puede intentar ejecutar cmd.exe en lugar de su archivo por lotes. Luego, utilizando los parámetros de la línea cmd de cmd.exe, puede hacer que IT inicie el archivo por lotes. Esto probablemente le proporcione una ventana de solicitud de cmd para ver el resultado real, si activa interactuar con el escritorio.
Para obtener ayuda completa sobre cmd.exe, simplemente escriba cmd /? en cualquier solicitud de comando.
Larry
pg_dump.exe probablemente esté solicitando la entrada del usuario. ¿Esta base de datos requiere autenticación? ¿Confía en alguna variable MEDIO AMBIENTE que no estará presente para el servicio? No sé pg_dump, pero ¿cuáles son las otras posibles razones por las que solicitaría la entrada?
¿Qué hace el archivo por lotes? ¿Está seguro de que el proceso se inicia con suficientes privilegios para ejecutar el archivo por lotes? Los servicios pueden estar limitados en lo que se les permite hacer.
También asegúrese de hacer algo como usar el comando de copia para sobrescribir un archivo y hacer algo como esto:
echo Y | copy foo.log c:/backup/
Además, asegúrese de estar utilizando rutas completas para los comandos por lotes, etc. Si el archivo por lotes está ejecutando una aplicación GUI en algún tipo de modo "Consola", eso también puede ser un problema. Recuerde, los servicios no tienen un "Escritorio" (a menos que habilite "interactuar con el escritorio") para dibujar cualquier tipo de ventana o cuadro de mensaje. En su programa, es posible que desee abrir los tubos stdout y stderr y leerlos durante la ejecución en caso de que reciba algún mensaje de error o algo por el estilo.
Es probable que WebServices se esté ejecutando como la cuenta IUSR, o la cuenta anónima, que sea, por lo que podría ser un problema para usted. Si funciona cuando lo ejecutas en la consola, ese es solo el primer paso. :)
No recuerdo si System.Diagnostics. están disponibles solo en depuración o no. Probablemente no, pero algunos de ellos podrían serlo. Tendré que verificar eso por ti.
Espero que esto te dé algunas ideas.
Larry
Aquí está la solución. La solución no está clara porque he cambiado tantas veces el código y ¡ahora está funcionando!
Intenté usar una Cuenta de usuario, y no funcionó. Use LocalSystem. Aquí está el código que se ejecuta, principalmente lo que Kevin me dio.
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = fileName;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
proc.WaitForExit();
output1 = proc.StandardError.ReadToEnd();
proc.WaitForExit();
output2 = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
Gracias a todos, voy a votar por todos y aceptar a Kevin, ya que me ayuda desde el principio. Muy raro porque funciona ahora ...
Daok, parece que lo único que cambiaste fue el tiempo de espera en el WaitForExit () inicial. Debes ser MUY cuidadoso con eso. Si algo cuelga su servicio, NUNCA volverá (y bueno, prácticamente funcionará como hasta ahora ha sido para usted ... heh), pero no será bueno para los usuarios finales ...
Ahora, quizás para saber qué está causando esto, puede depurarlo aún más y encontrar la solución completa ...
Eso, o bifurcarlo en algún hilo que puedas monitorear, y matar si se cuelga demasiado tiempo.
Solo mi valor de 2 centavos, que generalmente no es mucho. ;)
usando el sistema; utilizando System.Collections.Generic; utilizando System.Linq; usando System.Text; usando System.Diagnostics; espacio de nombres VG {clase VGe {[STAThread] static void Main (cadena [] args) {Process proc = null; tratar {
string targetDir = string.Format (@ "D: / adapters / setup"); // aquí es donde mybatch.bat se encuentra proc = new Process (); proc.StartInfo.WorkingDirectory = targetDir; proc.StartInfo.FileName = "mybatch.bat"; proc.StartInfo.Arguments = string.Format ("10"); // este es el argumento proc.StartInfo.CreateNoWindow = false; proc.Start (); proc.WaitForExit (); } catch (Exception ex) {Console.WriteLine ("Exception Occurred: {0}, {1}", ex.Message, ex.StackTrace.ToString ()); }}}}
string targetDir = string.Format(@"D:/");//PATH
proc = new Process();
proc.StartInfo.WorkingDirectory = targetDir;
proc.StartInfo.FileName = "GetFiles.bat";
proc.StartInfo.Arguments = string.Format("10");//argument
proc.StartInfo.CreateNoWindow = false;
proc.Start();
proc.WaitForExit();
Probado, funciona claro.
Esto es lo que uso para ejecutar archivos por lotes:
proc.StartInfo.FileName = target;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.UseShellExecute = false;
proc.Start();
proc.WaitForExit
(
(timeout <= 0)
? int.MaxValue : timeout * NO_MILLISECONDS_IN_A_SECOND *
NO_SECONDS_IN_A_MINUTE
);
errorMessage = proc.StandardError.ReadToEnd();
proc.WaitForExit();
outputMessage = proc.StandardOutput.ReadToEnd();
proc.WaitForExit();
No sé si eso hará el truco para ti, pero no tengo el problema de que se cuelgue.