web-dev-qa-db-fra.com

Comment terminer gracieusement un processus?

Je veux mettre fin à un certain nombre de processus, mais je veux donner à chaque processus la possibilité d'enregistrer ses données, demander à l'utilisateur de sauvegarder un fichier et même ignorer la demande de fermeture.

Donc TerminateProcess est hors de question, car il tue le processus instantanément. Une autre façon serait d'utiliser SendMessage/PostMessage pour envoyer un WM_CLOSE à la fenêtre principale, malheureusement je ne sais rien des fenêtres des processus, je n'ai que l'identifiant du processus, donc FindWindow n'aide pas non plus. Existe-t-il un autre moyen de trouver les fenêtres principales d'un processus?

En d'autres termes: Existe-t-il un moyen de terminer tout processus avec élégance, tout comme le fait le gestionnaire de tâches lorsque vous cliquez sur "- Fin de tâche "? (et non "End Process")

37
Daniel Rikowski

EnumWindows énumère toutes les fenêtres de niveau supérieur d'un processus. GetWindowThreadProcessId récupère le processus et l'ID de chaque thread.

Vous disposez désormais d'assez d'informations pour fermer gracieusement toute application graphique.

Vous pouvez envoyer WM_CLOSE messages vers n'importe quelle fenêtre que vous souhaitez fermer. De nombreuses fenêtres gèrent WM_CLOSE pour inviter l'utilisateur à enregistrer des documents. Vous pouvez envoyer un WM_QUIT message utilisant PostThreadMessage aux threads découverts pour provoquer la fin de la boucle de message.

Le code utilisateur n'est pas autorisé à appeler DestroyWindow à partir d'une application ou d'un thread différent vers les fenêtres ... si l'application ne répond pas à WM_CLOSE ou WM_QUIT demande que vous soyez de retour dans TerminateProcess land.

Cela ne fermera pas les applications de console car le processus d'application et le processus propriétaire de la fenêtre sont différents.


Reportez-vous à la réponse de T.s. Arun ci-dessous pour la méthode correcte de traitement des applications de console.

27
Chris Becke

Je ne suis pas trop sûr des API win32 mais vous pouvez utiliser Shell pour exécuter la fonction de ligne de commande taskkill.

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

Le commutateur/f forcerait la mise à mort mais ne pas l'utiliser envoie simplement le signal de terminaison de sorte que l'application se ferme correctement.

16
Andy E

Voir MSKB Q178893 Comment terminer une application "proprement" dans Win32 . Fondamentalement, envoyer envoyer WM_CLOSE à toutes les fenêtres de l'application cible pour permettre un arrêt de grâce, avant de forcer la suppression de l'application avec TerminateProcess

13
Sheng Jiang 蒋晟

Pour ajouter à Chris Becke répondre à la fin du processus de la console avec élégance.

AttachConsole () pour attacher à l'application console et envoyer un événement de rupture de contrôle, similaire à celui d'appuyer sur CTRL+C dans l'invite de commande.

Utilisation de GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, processID).

Cet événement de contrôle doit être géré dans l'application console pour une terminaison harmonieuse.

4
T.s. Arun

Utilisez la fonction API EndTask. C'est la même fonction que celle utilisée par le gestionnaire de tâches.

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

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

1
Jason

Vous pouvez utiliser taskkill/im your_program.exe pour envoyer un signal de terminaison à l'application. Il déclenchera un WM_CLOSE vers la file d'attente de messages Windows. Vous pouvez utiliser soit https://msdn.Microsoft.com/en-us/library/windows/desktop/ms633573 (v = vs.85) .aspx ou

https://docs.Microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getmessage

pour traiter le message.

Veuillez vous référer à une réponse similaire Win32 API analog of send/catching SIGTERM

0
amilamad