working - exit c# console application




Process.HasExited devuelve true aunque el proceso se está ejecutando? (8)

En primer lugar, ¿está seguro de que testprogram no genera un proceso propio y finaliza sin esperar a que finalice ese proceso ? Estamos tratando con algún tipo de condición de carrera aquí, y el programa de prueba puede ser significativo.

El segundo punto que me gustaría hacer es sobre esto: "Necesito estar absolutamente seguro de que este archivo de registro existe". Bueno, no hay tal cosa. Usted puede hacer su cheque, y luego el archivo se ha ido. La forma común de abordar esto no es verificar, sino hacer lo que quiere hacer con el archivo. Adelante, léelo, atrapa excepciones, vuelve a intentarlo si la cosa parece inestable y no quieres cambiar nada. El check-and-do funcional no funciona bien si tiene más de un actor (hilo o lo que sea) en el sistema.

Un montón de ideas al azar sigue.

¿Ha intentado usar FileSystemWatcher y no dependiendo de la finalización del proceso?

¿Se pone mejor si intentas leer el archivo (no verificando si existe, sino actuando en su lugar) en el proceso? ¿Evento emitido? [no debería]

¿Está el sistema sano? ¿Algo sospechoso en el registro de eventos?

¿Puede involucrarse alguna política antivirus realmente agresiva?

(No puedo decir mucho sin ver todo el código y sin mirar el programa de prueba).

He estado observando que Process.HasExited veces devuelve true aunque el proceso todavía se está ejecutando.

Mi código a continuación inicia un proceso con el nombre "testprogram.exe" y luego espera a que se cierre. El problema es que a veces me tiran la excepción; Parece que aunque HasExited devuelve true el proceso en sí sigue vivo en el sistema. ¿Cómo puede ser esto?

Mi programa escribe en un archivo de registro justo antes de que termine y, por lo tanto, debo estar absolutamente seguro de que este archivo de registro existe (también conocido como el proceso ha terminado / finalizado) antes de leerlo. La verificación continua de su existencia no es una opción.

// Create new process object
process = new Process();

// Setup event handlers
process.EnableRaisingEvents = true;
process.OutputDataReceived += OutputDataReceivedEvent;
process.ErrorDataReceived += ErrorDataReceivedEvent;
process.Exited += ProgramExitedEvent;

// Setup start info
ProcessStartInfo psi = new ProcessStartInfo
                           {
                               FileName = ExePath,
                               // Must be false to redirect IO
                               UseShellExecute = false,
                               RedirectStandardOutput = true,
                               RedirectStandardError = true,
                               Arguments = arguments
                           };

process.StartInfo = psi;

// Start the program
process.Start();

while (!process.HasExited)
    Thread.Sleep( 500 );

Process[] p = Process.GetProcessesByName( "testprogram" );

if ( p.Length != 0 )
    throw new Exception("Oh oh");

ACTUALIZACIÓN: Acabo de intentar esperar con process.WaitForExit() lugar del bucle de sondeo y el resultado es el mismo.

Adición: el código anterior solo era para demostrar un problema 'más claro' por igual. Para hacerlo claro; Mi problema NO es que todavía pueda obtener una retención del proceso por Process.GetProcessesByName( "testprogram" ); después de establecer HasExited en true.

El problema real es que el programa que estoy ejecutando externamente escribe un archivo, justo antes, termina (con gracia). Utilizo HasExited para verificar cuándo ha finalizado el proceso y, por lo tanto, sé que puedo leer el archivo (¡porque el proceso terminó!), Pero parece que HasExited devuelve true incluso a veces cuando el programa NO ha escrito el archivo en el disco todavía. Aquí hay un código de ejemplo que ilustra el problema exacto:

// Start the program
process.Start();

while (!process.HasExited)
    Thread.Sleep( 500 );
// Could also be process.WaitForExit(), makes no difference to the result

// Now the process has quit, I can read the file it has exported
if ( !File.Exists( xmlFile ) )
{
    // But this exception is thrown occasionally, why?
    throw new Exception("xml file not found");
}

Hay dos posibilidades, el objeto de proceso continúa manteniendo una referencia al proceso, por lo que ha salido, pero aún no se ha eliminado. O tienes una segunda instancia del proceso en ejecución. También debe comparar la identificación del proceso para asegurarse. Prueba esto.

    ....

    // Start the program
    process.Start();


    while (!process.HasExited)
        Thread.Sleep( 500 );

    Process[] p = Process.GetProcessesByName( "testprogram" );
    if ( p.Length != 0 && p[0].Id == process.id && ! p[0].HasExited)
        throw new Exception("Oh oh");

Me doy cuenta de que esta es una publicación antigua, pero en mi búsqueda para descubrir por qué mi aplicación ejecutó el evento Exited antes de que se abriera, descubrí algo que pensé que podría ser útil para las personas que experimentan este problema en el futuro.

Cuando se inicia un proceso, se le asigna un PID. Si luego se le solicita al usuario el cuadro de diálogo Control de cuenta de usuario y selecciona 'Sí', el proceso se reinicia y se le asigna un nuevo PID.

Me senté con esto por unas horas, espero que esto pueda ahorrarle tiempo a alguien.


Para empezar, ¿hay algún problema con el uso de Process.WaitForExit en lugar de sondearlo?

De todos modos, es técnicamente posible que el proceso salga desde un punto de vista utilizable, pero el proceso todavía es breve mientras hace cosas como vaciar el caché del disco. ¿Es el archivo de registro especialmente grande (o cualquier operación que esté realizando una gran cantidad de escrituras en el disco)?


Según la documentación de MSDN para HasExited .

Si un identificador está abierto para el proceso, el sistema operativo libera la memoria del proceso cuando el proceso ha salido, pero retiene información administrativa sobre el proceso, como el identificador, el código de salida y el tiempo de salida.

Probablemente no esté relacionado, pero vale la pena señalarlo.

Si solo es un problema 1/10 de las veces, y el proceso desaparece después de un segundo de todas formas, dependiendo de su uso de HasExited, intente agregar otra demora después de que la verificación HasExited funcione, como

while (!process.HasExited)
    DoStuff();
Thread.Sleep(500);
Cleanup();

y ver si el problema persiste.

Personalmente, siempre he usado el controlador de eventos Exited en lugar de cualquier tipo de sondeo, y un envoltorio personalizado simplista alrededor de System.Diagnostics.Process para manejar la seguridad de subprocesos, envolver una llamada a CloseMainWindow() seguido de WaitForExit(timeout) y finalmente Kill() , logging, etcétera, y nunca encontré un problema.


Si tiene una aplicación web y su programa / proceso externo está generando archivos (escribir en el disco), compruebe si su IIS tiene derechos para escribir en esa carpeta si no está en el permiso de seguridad de propiedades para su usuario de IIS, esa fue la razón en mi caso , estaba recibiendo process.HasExited = true, pero no se completaron los archivos del proceso, después de luchar durante un tiempo, agregué permisos completos a la carpeta donde el proceso se retorcía y procesaba.Refresh () como describió Zarathos desde arriba y todo estaba trabajando como se esperaba.


Te sugiero que lo intentes de esta manera:

process.Start();

while (!process.HasExited)
{
    // Discard cached information about the process.
    process.Refresh();

    // Just a little check!
    Console.WriteLine("Physical Memory Usage: " + process.WorkingSet64.ToString());

    Thread.Sleep(500);
}

foreach (Process current in Process.GetProcessesByName("testprogram"))
{
    if ((current.Id == process.Id) && !current.HasExited)
        throw new Exception("Oh oh!");
}

De todos modos ... en la página de MSDN de HasExited, estoy leyendo la siguiente nota destacada:

Cuando la salida estándar se ha redirigido a controladores de eventos asíncronos, es posible que el procesamiento de salida no se haya completado cuando esta propiedad devuelva verdadero. Para asegurarse de que se haya completado el manejo asíncrono de eventos, llame a la sobrecarga WaitForExit () que no requiere ningún parámetro antes de verificar HasExited.

Esto podría estar relacionado de alguna manera con su problema, ya que está redirigiendo todo.


Use process_name.Refresh() antes de verificar si el proceso ha salido o no. Refresh() borrará toda la información en caché relacionada con el proceso.





terminate