2009-12-26 9 views
5

He la sección siguiente código, diseñado para contar el número de procesos de Excel son actualmente abierto:Si 'Process.HasExited' arroja una excepción, ¿puedo suponer que el proceso se ha ido?

Func<int> OpenExcelProcessesCount = 
    () => System.Diagnostics.Process.GetProcessesByName("Excel") 
       .Where(p => !p.HasExited) 
       .Count(); 

Y luego más tarde recuperar el recuento en varios puntos, con código como el siguiente:

int excelAppCount = OpenExcelProcessesCount(); 

Este código ha estado funcionando 100% bien durante meses. Entonces, de repente, en la actualidad, se está constantemente me está dando una excepción que dice lo siguiente:

Exception: ApplicationThreadException 

Message: Access is denied 

Stack Trace: 

    at System.Diagnostics.ProcessManager.OpenProcess(Int32 

processId, acceso Int32, Boolean throwIfExited)

at System.Diagnostics.Process.GetProcessHandle(Int32 

acceso, Boole throwIfExited)

at System.Diagnostics.Process.get_HasExited() 

    etc... 

Básicamente, la llamada a Process.HasExited (que aparece como System.Diagnostics.Process.get_HasExited() en el seguimiento de pila, arriba) está fallando. El mensaje de error "Acceso denegado" parece que no tengo privilegios administrativos para el proceso, pero los únicos procesos de Excel que existen se crearán en mi inicio de sesión actual y el usuario siempre puede acceder a sus propios procesos. Mi código .NET también se ejecuta con plena confianza.

La línea que finalmente está fallando es System.Diagnostics.ProcessManager.OpenProcess(Int32 processId, Int32 access, Boolean throwIfExited). Me pregunto si se está pasando en un valor de 'verdadero' para el parámetro 'throwIfExited'. Si este es el caso, entonces supongo que podría proteger la llamada al Process.HasExited con un bloque try-catch y asumir que si esto falla, HasExited es, de hecho, 'verdadero'. ¿Pero es esto una suposición segura?

No me gusta hacer una presunción como esta, especialmente porque el mensaje de error es "Acceso denegado". ¿Alguien tiene alguna idea sobre cómo podría abordar esto, o qué podría probar en un intento de descubrir qué está pasando?

El único hilo similar que pude encontrar en Stack Overflow fue el siguiente: Why did hasExited throw ‘System.ComponentModel.Win32Exception’?. La respuesta no fue:

"Desde que está haciendo runas, sólo conseguir sincronizar el acceso en el mango, no PROCESS_QUERY_INFORMATION acceso, de ahí GetExitCodeProcess falla, que resultados en hasEnded lanzar una excepción Win32 . "

Realmente no entiendo esta respuesta y no sé si esto aplica en mi caso, pero pensé que debería mencionarlo. Si alguien siente que es probable que esta sea la situación a la que me enfrento, entonces, si alguien pudiera tratar de aclararme esta respuesta, lo agradecería mucho. (Yo soy un programador de Excel, no tengo mucha experiencia trabajando con los procesos.)

Muchas gracias de antemano ...

Actualización:

mejor que puedo decir, esto es era una corrupción única de algún tipo.Los problemas a los que me enfrenté comenzaron a ser cada vez más extraños ya que lo que había sido un conjunto de pruebas unitarias que funcionaba perfectamente comenzaba a tener fallas en otras ubicaciones "imposibles". Un simple reinicio corrigió este problema y todo lo demás que estaba enfrentando.

Mi mejor estimación es que tuve algún tipo de corrupción extraña. Quizás el ROT estaba corrugado, y/o tenía una instancia colgante de Excel que estaba tan corrupta que incluso las operaciones de 'Proceso' no eran necesariamente estables. Nada concluyente, pero esto es todo lo que puedo entender por ahora.

A los que respondieron que se tomaron el tiempo para responder y ayudarme, les agradezco.

+3

"Me pregunto si es que se pasa en un valor de 'verdadero' para el parámetro 'throwIfExited' ... ¿Esta es una suposición segura? ? " No. Según Reflector, HasExited pasa un valor de falso para throwIfExited. Además, si throwIfExited fuera verdadero, la excepción sería InvalidOperationException con un mensaje que indique que el proceso había finalizado. (Lo siento, no tengo una respuesta a su pregunta, pero pensé que valía la pena mencionar esto para no perder tiempo en una teoría infructuosa.) – itowlson

+0

Gracias, a mí mismo, realmente aprecio la información, esto definitivamente ayuda. –

Respuesta

4

La respuesta que cite puede aplicarse en su caso. Según tengo entendido, básicamente dice que si el proceso que está buscando se está ejecutando bajo una cuenta de usuario diferente, entonces HasExited no puede obtener los permisos que necesita para determinar si el proceso ha finalizado.

Ahora diga "los únicos procesos de Excel que existen se crearían en mi inicio de sesión de usuario actual". Pero supongamos que no es el caso. Supongamos que hay otro proceso de Excel ejecutándose en el mismo cuadro, bajo otra cuenta de usuario. (Tal vez uno comenzó por el proceso de otra persona usando OLE Automation, y no se limpió correctamente o se colgó.) Entonces GetProcessesByName lo recogió, pero HasExited fallaría.

Así que antes de llamar a su método OpenExcelProcessesCount(), agregue un poco de registro para volcar los ID de proceso de todos los procesos devueltos por GetProcessesByName ("Excel"). Luego, verifíquelos en el Administrador de tareas o en la cantidad de procesos de Excel que espera ejecutar bajo su cuenta. Si hay una identificación allí que no corresponde a un proceso de Excel "esperado", podría tener un culpable.

+0

Muchas gracias, realmente aprecio sus pensamientos y esfuerzos aquí. Voy a echarle un vistazo. No veo cómo podría ser un proceso creado en cualquier otro inicio de sesión, porque soy el único en esta máquina y no hay otras cuentas. Sin embargo, creo que una instancia corrupta/bloqueada de Excel * podría haber causado esto. Volveré después de más pruebas ... –

+0

Mi mejor suposición es que tuve algún tipo de corrupción extraña. El reinicio resolvió todo.Mi suposición es que el ROT estaba corrugado, y/o tenía una instancia colgante de Excel que estaba tan corrupta que incluso las operaciones de 'Proceso' no eran necesariamente estables. Nada concluyente, pero esto es todo lo que puedo entender por ahora ... agradezco la ayuda. –

1

Después de leer the documentation:

Utilice este método para crear una matriz de nuevos componentes de proceso y asociarse con todos los recursos de proceso que ejecutan el mismo archivo ejecutable en el equipo local.

Me parece que no necesita comprobar HasExited, ya que solo devuelve procesos en ejecución.

+0

Buen punto. Mi código es redundante en el mejor de los casos y equivale a una condición de carrera donde 'Process.HasExited' solo podía devolver 'falso' si un proceso devuelto por 'Process.GetProcessesByName' había salido en el microsegundo entre recibir la instancia 'Process' y probarla para 'HasExited'. Así que ahora he eliminado la llamada a 'HasExited'. El misterio anterior permanece, sin embargo, ¡pero gracias por tu ayuda! –

6

Process.HasExited puede lanzar una excepción de acceso denegado si el proceso de destino se está ejecutando elevado y su proceso no lo está. Lo mismo ocurre con la propiedad StartTime también.

Aquí hay un post sobre este tema con una posible solución: Bugs in System.Diagnostics.Process Class

+1

Gracias Giorgi, esta es realmente una buena información. –

+0

@MikeRosenblum: stacktrace también se parece al que tengo en el blog. – Giorgi

Cuestiones relacionadas