J'aimerais terminer un process cree avec CreateProcess avec ExitProcess et non TerminateProcess.
ExitProcess termine le process appelant. Comment utiliser dans ExitProcess le HANDLE retourne par CreateProcess ?
merci
J'aimerais terminer un process cree avec CreateProcess avec ExitProcess et non TerminateProcess.
ExitProcess termine le process appelant. Comment utiliser dans ExitProcess le HANDLE retourne par CreateProcess ?
merci
Raymond
Vous souhaitez participer à la rubrique Réseaux ? Contactez-moi
CafuroCafuro est un outil SNMP dont le but est d'aider les administrateurs système et réseau à configurer leurs équipements SNMP réseau.
e-verbeUn logiciel de conjugaison des verbes de la langue française.
Ma page personnelle sur DVP.
Il y a un moyen, mais c'est crade.
Mais paradoxalement, moins crade que TerminateProcess().
Néanmoins, ni l'un ni l'autre ne sont recommandés. La bonne méthode, c'est de dire à l'autre processus de se terminer (par un message Windows ou un autre mécanisme d'IPC).
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
2 points me genent:
* la doc de msdn dit explicitement d'utiliser ExitProcess(). C'est tres bizarre qu'on ne puisse pas l'utiliser
* dans la mesure ou CreateProcess() peut lancer n'importe quelle application, je ne peux pas savoir comment l'appli se termine (je fais un wrapper autour de CreateProcess, donc la commande qu'on lui passe n'est pas connue a l'avance)
Ben non, c'est pour quitter le processus courant. Elle recommande sans doute que le processus destination utiliser ExitProcess() pour quitter, c'est son droit (même si personnellement je trouve ça sale: Dans le cas idéal, un processus se termine quand tous ses threads se sont terminés, mais de nos jours il y a tellement de fonctions qui créent un thread en arrière-plan que ça n'est plus réaliste, et le code appelle automatiquement ExitProcess() quand la fonction main() retourne).
Et pourtant, tu autorises à tuer le processus créé? Ben tu ne peux pas avoir le beurre et l'argent du beurre, ni être sâle et propre à la fois. D'un autre côté, tu peux essayer plusieurs méthodes successives, comme le fait le gestionnaire de tâches: Envoyer des messages de fin à ses fenêtres, puis si ça ne marche pas, à son thread principal, puis si ça ne marche toujours pas, tuer le processus...* dans la mesure ou CreateProcess() peut lancer n'importe quelle application, je ne peux pas savoir comment l'appli se termine (je fais un wrapper autour de CreateProcess, donc la commande qu'on lui passe n'est pas connue a l'avance)
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
le thread principal, c'est celui qui se trouve dans le PROCESS_INFORMATION rempli par CreateProcess ?
Oui.
Disons que c'est le premier thread créé, et que c'est généralement celui utilisé pour l'interface utilisateur (je pense notamment que ça n'est pas le cas pour les applications Java).
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
C'est surtout que si ce thread principal se termine, ton process se termine également. Donc, les autres threads du processus se font flinguer au passage...
En règle générale, pour qu'il ne se termine pas sans prévenir, on y met justement la boucle de messages Windows, ça occupe utilement le thread principal justement.
Mac LAK.
___________________________________________________
Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.
Sources et composants Delphi sur mon site, L'antre du Lak.
Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.
Rejoignez-nous sur : ► Serveur de fichiers [NAS] ► Le Tableau de bord projets ► Le groupe de travail ICMO
Seulement s'il se termine par un retour du main.
On peut explicitement le terminer avec ExitThread() pour éviter cela, mais ça n'est pas recommandé parce que certains composants du systême (comme COM) peuvent créer des threads sur lesquels tu n'as aucun contrôle, et qui empêchent le processus de se terminer naturellement quand tous les threads "à toi" sont terminés.
Edit: En bonus, l'article du lendemain. Quand je disais que ExitProcess() était sale...
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Le thread principal, c'est celui exécutant le main, justement...
Faudrait essayer pour le fun, mais je doute fortement que flinguer le thread principal (via TerminateThread, tant qu'à faire soyons crades jusqu'au bout) depuis un thread / processus à part permette au processus de continuer à tourner.
Mac LAK.
___________________________________________________
Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.
Sources et composants Delphi sur mon site, L'antre du Lak.
Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.
Rejoignez-nous sur : ► Serveur de fichiers [NAS] ► Le Tableau de bord projets ► Le groupe de travail ICMO
Je l'ai déjà fait: Thread principal lance un second thread, second thread fait un truc (comme afficher des messages toutes les secondes pendant dix secondes), premier thread appelle ExitThread() au lieu de sortir du main()...
PS: Doc à l'appui
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
"ExitThread()", c'est "propre" (enfin... c'est relatif, hein) par rapport à "TerminateThread()"... Enfin, ça reste juste de la curiosité quoi qu'il en soit vu que cela reste du code "crade" si ce n'est pas fait correctement, avec la coopération propre du processus que l'on veut terminer.
Mac LAK.
___________________________________________________
Ne prenez pas la vie trop au sérieux, de toutes façons, vous n'en sortirez pas vivant.
Sources et composants Delphi sur mon site, L'antre du Lak.
Pas de question technique par MP : posez-la dans un nouveau sujet, sur le forum adéquat.
Rejoignez-nous sur : ► Serveur de fichiers [NAS] ► Le Tableau de bord projets ► Le groupe de travail ICMO
donc pour résumer, j'appelle CreateProcess. Si pi est la structure PROCESS_INFORMATION remplie par CreateProcess, j'appelle CloseHandle sur pi.hProcess (je n'en ai pas besoin). Puis si plus tard je veux arreter l'application lancee par CreateProcess:
- J'appelle CloseHandle(pi.hThread)
- Si ca foire, J'appelle TerminateProcess(pi.ProcessId, 0)
c'est ca ? Notez que j'appelle CloseHandle et pas ExitThread car c'est ce qui est indique dans la doc de CreateProcess
Non.
Vous demandez au process que vous avez créé de se terminer. Le canal de communication avec le process créé est fonction de celui-ci.
On ne "demande" pas à un programme de se terminer par un TerminateThread() sur son premier thread. Entre autres, c'est une des choses qui laissera tourner les autres threads, puisque le premier thread n'aura pas appelé ExitProcess().
La méthode que je propose, c'est plus:
- EnumWindows() + GetWindowThreadProcessId() + PostMessage(WM_CLOSE)
- et si ça ne marche pas, PostThreadMessage(WM_QUIT)
- si ça ne marche pas, et si tu en as la volonté, on peut tester plus sournois: CreateRemoteThread(ExitProcess) mais ça a tendance à planter certaines applications, et donc à lancer DrWatson. Étrangement, comme ça prévient les DLLs, je me demande parfois si ça n'est pas plus propre que TerminateProcess()...
- Quand tout le reste a échoué, TerminateProcess().
PS: TerminateProcess() nécessite un handle, pas un ID.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Un code comme ceci pour le callback ?
Je ne suis pas sur si il faut que je passe NULL pour les attributs de securite de CreateRemoteThread.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 static DWORD WINAPI _ecore_exe_thread_procedure(LPVOID data) { ExitProcess(0); return 1; } static BOOL CALLBACK _ecore_exe_enum_windows_procedure(HWND window, LPARAM data) { Ecore_Exe *exe; DWORD thread_id; exe = (Ecore_Exe *)data; thread_id = GetWindowThreadProcessId(window, NULL); if (thread_id == exe->thread_id) { if (PostMessage(window, WM_CLOSE, 0, 0)) return FALSE; if (PostThreadMessage(thread_id, WM_QUIT, 0, 0)) return FALSE; if (CreateRemoteThread(exe->process, NULL, 0, _ecore_exe_thread_procedure, NULL, 0, NULL)) return FALSE; } return TRUE; }
Concernant l'utilisation de TerminateProcess(), comme je fais un port Windows d'une bibliotheque Linux et que celle-ci utilise les signaux d'interruption, je ne sais pas s'il faut que je l'utilise tout le temps ou pas. Je demanderai au developpeur principal.
Au passage, j'ai utilise OpenProcess() apres CreateProcess pour modifier les attributs du processus. Dois-je toujours appeler CloseHandle sur le HANDLE retourne par cette donction ? Ou bien ceci est gerer par certains appels du code ci-dessus ?
merci en tout cas !
Non, la Callback doit être directement ExitProcess().
Et normalement, il faudrait regarder où se trouve la fonction dans la DLL (calculer son offset) et où se trouve la DLL dans le processus destination. Mais bon, comme il s'agit de Kernel32, on peut s'en passer (du moins sous XP).
Note aussi que cette tactique, peut-être même avec le calcul d'offset, peut être invalidée par l'introduction de mécanismes d'ASLR (Address Space Layout Randomization) sous Windows Vista.
Edit: Apparemment, l'ASLR de Vista ne change que l'emplacement des DLLs en mémoire, donc un calcul d'offset devrait contourner la protection.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Pour calculer l'offset, ceci devrait suffire:
Code C : Sélectionner tout - Visualiser dans une fenêtre à part ptrdiff_t offsetExit = (char const*)GetModuleHandle("kernel32.dll") - (char const*)&ExitProcess;
Ensuite, il faut trouver la DLL dans l'autre processus. À l'époque, j'avais utilisé CreateToolHelp32Snapshot() et Module32First()/Module32Next(), mais EnumProcessModules() suffit peut-être.
SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.
"Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
Apparently everyone. -- Raymond Chen.
Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.
Heu, je veux peut-être dire une connerie mais si la version Linux fait des Kill -9 sur ces fils, il peut faire aussi crade sous Windows.
Si c'est des signaux USR1 ou USR2, pourquoi ne pas câbler les routines d'interruption sur signal sous Linux dans la pompe à message de la fenêtre principale sur les messages WM_APP et WM_APP+1 ?
C'est juste pour faire aussi basic que sous Linux.
Partager