2010-08-17 18 views
5

Nuestra aplicación tiene un hilo de fondo que genera un proceso a través System.Diagnostics.Process:proceso generado a través Process.Start en .NET cuelga el hilo

Process.Start(
    new ProcessStartInfo 
    { 
     FileName = url, 
     UseShellExecute = true 
    } 
); 

Esto solía tener ningún problema en absoluto. Pero ahora, el hilo de fondo está muriendo silenciosamente; nunca regresa de la llamada al Process.Start. El bloque catch para este código, que maneja System.Exception, tampoco está siendo alcanzado. Incluso si habilito el manejo de excepciones cuando se lanza en el depurador de Visual Studio, no veo excepciones. Extrañamente, el proceso se engendra perfectamente; el navegador predeterminado para el usuario se inicia con la URL esperada.

El punto de entrada de nuestro proceso está marcado con [STAThread] como se recomienda.

¿Qué podría estar causando que nuestro hilo termine silenciosamente? ¿Hay alguna técnica que pueda usar para depurar lo que está sucediendo durante la terminación del hilo?

Actualización:

Parece que el hilo está vivo después de todo; simplemente no regresa de la llamada. Aquí está su seguimiento de la pila:!!

  • [En una espera de sueño o unirse]
  • System.dll System.Diagnostics.ShellExecuteHelper.ShellExecuteOnSTAThread() + 0x63 bytes
  • System.dll System.Diagnostics.Process .StartWithShellExecuteEx (System.Diagnostics.ProcessStartInfo startInfo) + 0x19d bytes
  • System.dll! System.Diagnostics.Process.Start (+) 0x39 bytes
  • System.dll! System.Diagnostics.Process.Start (System.Diagnostics .ProcessStartInfo startInfo) + 0x32 bytes
  • Mi método

Actualización 2:

cmd.exe lanzamiento sin utilizar el shell para ejecutar obras como una solución. ¡Gracias un montón! Sin embargo, todavía me gustaría saber por qué la llamada no está regresando.

Actualización 3:

ganchos Shell suenan como una explicación lógica para lo que podría ser la causa de la llamada a no volver. No pude encontrar el módulo falso, pero después del último intento de ejecutar cosas a través de la ejecución del shell, la llamada hizo devolver.

En cualquier caso, es posible que los usuarios tengan cargadas extensiones de caparazón que podrían interferir con el inicio del proceso y hacer que mi código no regrese. No podemos hacer nada sobre que, por lo que la respuesta correcta es utilizar la solución alternativa de iniciar un proceso cmd.exe.

Respuesta

4

Según lo mencionado por Hans Passant, una llamada colgante Process.Start podría ser la razón. Cuando se utiliza Process.Start con UseShellExecute establecido en true, se llama a la función API de Windows ShellExecuteEx bajo el cofre que podría no volver en determinadas circunstancias.

Puede comprobar si este es el caso, añadiendo mensajes de seguimiento a su código:

System.Diagnostics.Trace.WriteLine("About to start process."); 
Process.Start(
    new ProcessStartInfo 
    { 
     FileName = url, 
     UseShellExecute = true 
    } 
); 
System.Diagnostics.Trace.WriteLine("Process started."); 

Para escuchar los mensajes de seguimiento que puede utilizar un TraceListener, comprobar la ventana de resultados de Visual Studio o utilizar una herramienta como DebugView.

Como solución alternativa, puede usar el comando start. El siguiente código inicia una ventana de shell oculta que "inicia" la url:

Process.Start(
    new ProcessStartInfo() 
    { 
     FileName = "cmd.exe", 
     Arguments = "/c start http://www.google.com", 
     WindowStyle = ProcessWindowStyle.Hidden, 
     UseShellExecute = false 
    }); 
+0

No hay sorpresas con las adiciones 'Trace.WriteLine'; el "Proceso iniciado". línea no alcanzada – Jacob

+0

Al iniciar cmd.exe, la llamada sigue sin aparecer. – Jacob

+0

Bah, pero lo hace si convierto a UseShellExecute en falso. – Jacob

4

Nah, los hilos no terminan silenciosamente, hacen un sonido de kaboom fuerte. Como mínimo, verá la notificación de salida de subproceso en la ventana Salida. El bloqueo del método Process.Start() sería otra explicación, aunque no hay explicación para eso. Tu fragmento es demasiado corto para llegar a un diagnóstico decente. Algo ambiental tal vez.


Su seguimiento de la pila ayuda, ShellExecuteOnSTAThread() no en el hecho de realizar una Thread.Join bloqueo() en un pequeño hilo ayudante. Este hilo es necesario para llamar a la función API nativa ShellExecuteEx(), solo se puede invocar desde un hilo STA. Sin embargo, tiene un defecto, un hilo STA también debe bombear un bucle de mensaje. Este pequeño ayudante no.

Que esto cause un problema en su máquina aún apunta a un problema ambiental, algún tipo de complemento del sistema que secuestra la llamada ShellExecuteEx(). Y cuenta con ejecutar un hilo STA real. Debería poder encontrar ese hilo auxiliar en la ventana Debug + Windows + Threads. Debe contener "ShellExecuteFunction" en la pila. El tipo de 'complemento del sistema' que realiza acrobacias como esta son los escáneres de virus, por ejemplo. Debería poder encontrar ese alienware en la ventana Debug + Windows + Modules después de marcar la opción "Habilitar la depuración no gestionada" en la pestaña Depuración del proyecto.

La solución para utilizar UseShellExecute = false es bastante aceptable aquí por cierto. El simple hecho de que su máquina esté un poco estropeada, por su aspecto, no es, por supuesto.

+0

Comprobé la ventana de salida en Visual Studio y no se produjo ningún resultado después de iniciar 'Process.Start'. Consideré la posibilidad de que la llamada estuviese bloqueando, pero incluso después de terminar todas las instancias de Chrome, la llamada nunca volvió (aunque con 'UseShellExecute' no tengo idea de por qué se bloquearía la llamada) – Jacob

+0

Bien, use el depurador. Mira la pila de llamadas. Un depurador no administrado con el servidor de símbolos de Microsoft configurado probablemente sea el mejor. –

+0

Un gran consejo, @Hans. Encontrado más información. Ver la actualización de mi pregunta. – Jacob

Cuestiones relacionadas