El servicio se cuelga en WaitForExit después de llamar al archivo por lotes

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.

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.

 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; namespace VG { class VGe { [STAThread] static void Main(string[] args) { Process proc = null; try { string targetDir = string.Format(@"D:\adapters\setup");//this is where mybatch.bat lies proc = new Process(); proc.StartInfo.WorkingDirectory = targetDir; proc.StartInfo.FileName = "mybatch.bat"; proc.StartInfo.Arguments = string.Format("10");//this is argument 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.

¿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 progtwig, 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

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?

El siguiente paso que tomaré es encender el depurador y ver si puede decir qué espera el progtwig. 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

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. 😉