2009-01-22 11 views
6

Tengo un proceso de actualización automática implementado en el cual mi aplicación principal exe ejecuta un exe actualizador pasando un manejador a sí mismo en la línea de comando. El exe de la aplicación llama a ExitProcess para salir y el actualizador llama a WaitForSingleObject en el controlador pasado para esperar a que finalice el exe de la aplicación.¿Cuándo Windows señala un identificador de proceso?

WaitForSingleObject espera. Hasta que la aplicación llame a ExitProcess, el actualizador se detiene.

Sin embargo, a veces, cuando el actualizador intenta sobrescribir los archivos DLL de la aplicación con las nuevas versiones, aparece un error de archivo bloqueado que la versión actual de mi actualizador trata como un error irrecuperable y finaliza. Parece que incluir un sueño arbitrario (100) es suficiente para eludir este "problema", pero realmente odio el código así. realmente odio.

Me parece muy extraño que el identificador del proceso se pueda señalar mientras la aplicación principal todavía está viva lo suficiente como para tener archivos dll bloqueados.

Respuesta

1

Como otra respuesta señala, el mango proceso se señala cuando el proceso se ha detenido la ejecución y el sistema operativo podría tardar un poco más para liberar DLL.

Tiene razón en que confiar en Sleep (100) es una mala idea.Usted no debe envolver sobrescribir los archivos DLL en un bucle como este:

BOOL UpdateDll(LPCTSTR dll_name, WHATEVER whatever) { 
    int tries = 150; 
    while (tries--) { 
    if (TryUpdateDll(dll_name, whatever)) 
     return TRUE; 
    Sleep(200); 
    } 
    return FALSE; 
} 

Esto sigue tratando de descargar el archivo DLL durante 30 segundos y luego se da por vencido. 30 segundos deberían ser suficientes incluso cuando el sistema está bajo una carga pesada, pero aún así protegerán su actualizador para que no se cuelgue para siempre. (En caso de que UpdateDll devuelva FALSE, asegúrese de presentar un mensaje de error significativo a su usuario, indicando el nombre de la DLL ofensiva).

Si está jugando con COM, una llamada a CoFreeUnusedLibraries antes de salir también puede ser útil. (http://msdn.microsoft.com/en-us/library/ms679712.aspx) Francamente, no sé si COM podría aferrarse a las DLL incluso después de que su proceso finalice, pero es mejor estar seguro.

En pocas palabras es que hay mucha extrañeza en la API de Win32. No tiene que lidiar con todos los casos siempre que pueda encontrar una solución aceptable. Obviamente Sleep (100) podría romperse, pero un ciclo de sondeo de 30 segundos me parece aceptable.

2

El proceso se emite cuando sale el código de la aplicación. El OS puede tardar un poco más en descargar el proceso por completo. El punto de señalización es decir "He terminado de hacer lo que necesito hacer", es más eficaz para lanzar otro código que puede tener cosas realmente útiles que hacer en lugar de hacer que ese código espere mientras el sistema operativo realiza algunas tareas domésticas.

+0

Parece que, prácticamente, el identificador del proceso se señaliza tan pronto como haya un código de salida válido para devolver desde GetExitCode(). Pero, en términos de casos de uso común, las aplicaciones que probablemente esperarán en los identificadores de proceso son los instaladores/actualizadores que necesitan saber cuándo pueden eliminar cosas. –

0

Podría ser que las DLL estén bloqueadas por algún otro proceso en ese momento. Una forma de probar esto sería generar un informe de lo que sea que tenga en la DLL cuando esto suceda.

0

Vi una erupción de estos con algunos programas antivirus hace unos seis meses. Pruebe sin AV y, como mínimo, asegúrese de que el AV esté actualizado.

0

Si cualquiera de los DLL que está utilizando es el uso de hilos, que no pueden terminar (o unirse a) lo suficientemente rápido si no se descarguen de manera explícita ellos- que por supuesto ocurrir si los hubiera cargado de forma explícita utilizando LoadLibrary

Echa un vistazo aquí: http://msdn.microsoft.com/en-us/library/ms682596(VS.85).aspx

Específicamente esta línea:

... la DLL se descarga cuando el proceso termina o llama al FreeLib función de rary y el recuento de referencia se convierte en cero. Si el proceso finaliza como resultado de la función TerminateProcess o TerminateThread , el sistema no llama a la función de punto de entrada DLL .

0

una posible solución para usted ... aunque no puede reemplazar el dll que se utiliza, puede cambiarle el nombre. así que si tiene un dll que necesita reemplazar, pero está en uso por algún motivo, cámbiele el nombre a .delete o algo así. haga la actualización, luego haga que su programa principal busque cualquier archivo .delete y elimínelos cuando se inicie.

-don

Cuestiones relacionadas