2010-01-13 23 views
32

Quiero terminar una serie de procesos, pero quiero dar a cada proceso la oportunidad de guardar sus datos, preguntarle al usuario sobre guardar un archivo e incluso ignorar la solicitud de cierre.Cómo finalizar correctamente un proceso?

Así que TerminateProcess está fuera de la cuestión, ya que mata el proceso al instante. Otra forma sería usar SendMessage/PostMessage para enviar un WM_CLOSE a la ventana principal, desafortunadamente no sé nada sobre las ventanas de los procesos, solo tengo la identificación del proceso, por lo que FindWindow tampoco ayuda. ¿Hay alguna otra manera de encontrar las ventanas principales de un proceso?

En otras palabras: ¿Hay alguna manera de poner fin a cualquier proceso con gracia al igual que lo hace el administrador de tareas cuando se hace clic en "Finalizar tarea "? (y no "End Process")

+0

que asumen que "tareas" son ventanas de nivel superior (visibles). Por lo tanto, el 'WM_CLOSE' se enviará (probablemente) en la tarea de finalización. –

+0

Si no es un desarrollador de software, solo un usuario de Windows, consulte [la pregunta relacionada con el Superusuario sobre cómo solicitar con gracia que finalice una aplicación en ejecución] (http://superuser.com/questions/959364/on-windows- cómo-puedo-yo-agradecer-pedir-un-proceso-terminar). – unforgettableid

+0

Tenga en cuenta que, a partir de Windows 8.1, el botón "Finalizar tarea" del Administrador de tareas ahora termina a la fuerza la aplicación elegida y hace que pierda cualquier trabajo no guardado.Es posible que desee editar su pregunta para reflejar esto. – unforgettableid

Respuesta

22

EnumWindows enumera todas las ventanas de nivel superior en un proceso. GetWindowThreadProcessId obtiene el proceso y Id de cada hilo.

Ahora tiene suficiente información para cerrar con gracia cualquier aplicación GUI.

Puede enviar WM_CLOSE mensajes a cualquier ventana que desee cerrar. Muchas ventanas manejan el WM_CLOSE para solicitar al usuario que guarde documentos. Puede enviar un mensaje WM_QUIT usando PostThreadMessage a los hilos descubiertos para hacer que el ciclo del mensaje finalice.

código de usuario no está autorizado a llamar DestroyWindow de una aplicación o subproceso diferente a las ventanas ... si la aplicación no responde a las peticiones WM_CLOSE o WM_QUIT que está de vuelta en la tierra TerminateProcess.

Esto no cerrará las aplicaciones de la consola ya que el proceso de la aplicación y el proceso que posee la ventana son diferentes.

No hay una forma real de cerrar las aplicaciones de la consola correctamente en Windows. Necesitan apoyar algún tipo de mecanismo cerrado elegante.

+0

Cuando tengo todas las ventanas del proceso, ¿envío un 'WM_CLOSE' a cada ventana de nivel superior? –

+0

Exactamente lo que iba a decir. +1. –

+2

Sí - TaskManager envía un mensaje 'WM_CLOSE' a la aplicación. En realidad, creo que podría enviar un mensaje 'WM_SYSCOMMAND',' SC_CLOSE'. –

15

No estoy muy seguro acerca de las API de Win32, pero podría ejecutar la función de línea de comandos taskkill.

taskkill /? 
taskkill /pid 1230 
taskkill /im notepad.exe 

El modificador/f obligaría a la matanza, pero no usarlo simplemente envía la señal de terminación por lo que la aplicación se cierra con gracia.

+4

Desafortunadamente, esto solo está disponible en Windows XP Professional o posterior. (Ni siquiera XP en casa), pero también necesito esa funcionalidad para Windows 2000 y XP Home. Pero me encantaría ver el código fuente de esa herramienta :) –

13
+0

+1. Se superpone mucho con la solución de Chris Becke, además de manejar casos de esquina con aplicaciones de 16 bits. Bonito. –

+9

También debe escribir parte del contenido aquí en caso de que la página se baje o se mueva. – MasterMastic

+0

Las respuestas con solo el enlace no son buenas respuestas. Por favor haz lo que MasterMastic sugirió y pon el contenido sustantivo en esta respuesta. –

1

Utilice la función API EndTask. Es la misma función que usa el administrador de tareas.

BOOL EndTask(  
    HWND hWnd, 
    BOOL fShutDown, 
    BOOL fForce 
); 

http://msdn.microsoft.com/en-us/library/ms633492(VS.85).aspx

+7

La primera línea de texto en esa página dice: * [Esta función no está destinada para uso general. Puede estar alterado o no disponible en versiones posteriores de Windows.] *. ¿Quizás los videntes no hicieron clic? – Jon

+2

@Jon muchas API tienen esa pista, pero muchos problemas no se pueden resolver sin usarlos. Lo mismo se aplica a los "indocumentados". (No digo que este sea uno de esos casos) –

Cuestiones relacionadas