[C++] Exécution d'un programme dos [les bizarreries de windows]

Exécution d'un programme dos [les bizarreries de windows] [C++] - C++ - Programmation

Marsh Posté le 22-07-2002 à 09:21:20    

Via la fonction ShellExecute je lance un programme dos mais le problème c'est que ce programme dos ne se ferme pas automatiquement à la fin du programme : il ya le message bien connu Microsoft Popup windows Presser Ctrl+C pour fermer et retourner sous windows. J'aimerais bien éviter ce message. Il est possible de le faire en cochant la case "Fermer en quittant" dans les propriétés mais comment le faire en C++ ?
Avez vous une idée pour fermer cette fenêtre dos sans attendre le Ctrl-C ?
merci
 ANT


Message édité par antsite le 22-07-2002 à 09:28:15
Reply

Marsh Posté le 22-07-2002 à 09:21:20   

Reply

Marsh Posté le 22-07-2002 à 11:21:44    

j'ai pas la solution mais ca m'interesse donc ..... up

Reply

Marsh Posté le 22-07-2002 à 11:25:18    

J'ai trouvé pas mal de trucs dans msdn mais rien n'y fait...
 
GenerateConsoleCtrlEvent -> ça devrait être ça mais je n'ai pas réussi à faire marcher cette fonction, elle me renvoie toujours une erreur. Même avec cette fonction SetConsoleCtrlHandler qui active bien le Ctrl-C...

Reply

Marsh Posté le 22-07-2002 à 11:27:01    

Bah, t'as qu'a, une fois que le batch (ou autre) est fini, envoyer un WM_CLOSE à la fenêtre...
non !?

Reply

Marsh Posté le 22-07-2002 à 11:28:35    

Dans quel cas windows te demande d'appuyer sur Ctrl+C? comment cela se fait-il?

Reply

Marsh Posté le 22-07-2002 à 11:40:47    

Je m'étais dit qu'en utilisant CreateProcess au lieu de ShellExecute on pourrait contourner le problème avec ça :
 
WaitForInputIdle(pinfo.hProcess,INFINITE);
GetExitCodeProcess(pinfo.hProcess,&ecode);
ExitProcess(ecode);
 
mais je ne sais pas pourquoi ce code me ferme mon app et non le processus lancé  :pt1cable:  
Pourtant dans createprocess j'ai mis false à inheritance...
 
De plus je n'arrive pas à fermer la console : SendMessage((HWND)pinfo.hProcess,WM_CLOSE,0,0); ne fonctionne pas (WM_DESTROY) non plus.
 
J'ai ce message lorsque je quitte une app dos lancée sous windows sans avoir coché l'option "Fermer en quittant" dans les propritétés du prog

Reply

Marsh Posté le 22-07-2002 à 11:51:02    

ExitProcess quitte le process dans lequel elle est exécutée.
 
Utilise terminateProcess ou bien envoie le ctrl-C à ton prog.


---------------
Le Tyran
Reply

Marsh Posté le 22-07-2002 à 11:55:13    

letoII a écrit a écrit :

ExitProcess quitte le process dans lequel elle est exécutée.
 
Utilise terminateProcess ou bien envoie le ctrl-C à ton prog.




 
envoyer Ctrl-C, ou, plus simple, envoyer WM_CLOSE.
C plus propre qu'un terminate process...

Reply

Marsh Posté le 22-07-2002 à 11:57:30    

el_gringo a écrit a écrit :

 
 
envoyer Ctrl-C, ou, plus simple, envoyer WM_CLOSE.
C plus propre qu'un terminate process...




 
tout à fait d'accord


---------------
Le Tyran
Reply

Marsh Posté le 22-07-2002 à 12:10:20    

C'est sur mais le problème c'est que je ne sais pas comment récupérer le HWND du process créé. J'ai essayé de caster la HANDLE hProcess mais ça ne marche pas, ça ne doit pas être le hwnd de la console.
J'ai pas XP donc je peux faire une croix sur GetConsoleWindow()...
 
En plus le code suivant ne marche pas, je pige que dale  :ouch:  
GetExitCodeProcess(pinfo.hProcess,&ecode);
TerminateProcess(pinfo.hProcess,ecode);


Message édité par antsite le 22-07-2002 à 12:16:15
Reply

Marsh Posté le 22-07-2002 à 12:10:20   

Reply

Marsh Posté le 22-07-2002 à 12:30:34    

Tu fais un EnumWindows pour trouver le hWnd de la console, puis tu lui balance un WM_CLOSE, et roulez jeunesse :)


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2002 à 12:30:46    

antsite a écrit a écrit :

C'est sur mais le problème c'est que je ne sais pas comment récupérer le HWND du process créé. J'ai essayé de caster la HANDLE hProcess mais ça ne marche pas, ça ne doit pas être le hwnd de la console.
J'ai pas XP donc je peux faire une croix sur GetConsoleWindow()...
 
En plus le code suivant ne marche pas, je pige que dale  :ouch:  
GetExitCodeProcess(pinfo.hProcess,&ecode);
TerminateProcess(pinfo.hProcess,ecode);




 
Ha non, caster le hProcess, ça va pas du tout !
Un fenêtre, c pas la même chose qu'un process, tu l'sais bien qd même. non !?
tu peux utiliser ça :
 

Code :
  1. //------------------------------------------------------------------------------------------------------------
  2. // Termine une application Win32 "proprement"
  3. // Paramètre : Handler du process à killer et temps d'attente avec de terminer le processus "brutalement"
  4. // Retour    : BOOL, TRUE si kill réussi
  5. //       FALSE si raté
  6. //------------------------------------------------------------------------------------------------------------
  7. BOOL CLanSession::TerminateApp(DWORD _dwPID, DWORD _dwTimeOut)
  8. {
  9. HANDLE hProc;
  10. DWORD  dwRetour;
  11. hProc = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE, FALSE, _dwPID);
  12. if (hProc == NULL)
  13.  return FALSE;
  14. EnumWindows ((WNDENUMPROC) TerminateAppEnum, (LPARAM) _dwPID);
  15. if (WaitForSingleObject(hProc, _dwTimeOut) != WAIT_OBJECT_0)
  16.  dwRetour = TerminateProcess (hProc, 0) ? TRUE:FALSE;
  17. else
  18.  dwRetour = TRUE;
  19. CloseHandle (hProc);
  20. return dwRetour;
  21. }
  22. //-----------------------------------------------------------------------------------------------------------
  23. // poste un message WM_CLOSE à toutes les fenêtres dont le PID concorde avec celui du process
  24. //-----------------------------------------------------------------------------------------------------------
  25. BOOL CALLBACK TerminateAppEnum (HWND _hWnd, LPARAM _lParam)
  26. {
  27. DWORD dwID;
  28. GetWindowThreadProcessId(_hWnd, &dwID);
  29. if (dwID == (DWORD)_lParam)
  30.  PostMessage(_hWnd, WM_CLOSE, 0, 0);
  31. return TRUE;
  32. }


 
(c du copier/coller en brute, j'éspère que ça va être lisible)


Message édité par El_gringo le 22-07-2002 à 12:32:31
Reply

Marsh Posté le 22-07-2002 à 12:33:11    

...c un extrait du mon 1er prog C(++ ?), soyez indulgents !

Reply

Marsh Posté le 22-07-2002 à 13:32:18    

Merci beaucoup à tous les 2, ça marche très bien.
Seulement un dernier petit ennui : si on veut fermer proprement la console via un message WM_CLOSE, il apparait une boîte de dialogue disant un truc du genre : Etes vous sur de vouloir fermer la fenêtre... Infos non sauvegardées... Comment eviter ce msg ? WM_DESTROY fonctionne encore moins, il n'essaye même pas de fermer la console (pas de popup de confirmation).

Reply

Marsh Posté le 22-07-2002 à 13:41:26    

Je vais me mêler de ce qui ne me regarde pas, mais n'aurait-il pas été plus simple de créer dans le progr C un raccourci vers l'exécutable "DOS", raccourci comportant les paramètres pour fermer la fenêtre en quittant, puis de lancer le raccourci ?
A+

Reply

Marsh Posté le 22-07-2002 à 13:44:34    

Tout à fait mais j'ignore comment faire ce raccourci avec le paramètre voulu !

Reply

Marsh Posté le 22-07-2002 à 13:56:28    

Pour reprendre l'idée de WM_CLOSE je pensais que plus simplement pour éviter la popup il faudrait lui envoyer ce qu'il demande à savoir Ctrl+C. Seulement je n'y arrive pas, je comprends pas la msdn. Comment envoyer Ctrl+C ?
WM_KEYDOWN
wParam: 'c'
lParam: ???? je comprends pas comment ça marche ce lParam, comment lui dire que Ctrl est pressée ?

Reply

Marsh Posté le 22-07-2002 à 14:04:19    

c'est un champ de bits. le bit 29 te permet de dire si une touche étendue est enfoncée ou pas (1 = pressée).
 
verifie le msdn sur WM_KEYDOWN pour plus d'infos. mais moi je te conseillerais plutot WM_KEYUP, car il peut se produire plusieurs KEYDOWN avant un KEYUP
 
j'ai jamais compris d'ailleurs pq tout le monde utilisait WM_KEYDOWN ! il me semble que WM_KEYUP est bien plus significatif puisqu'il se produit une fois que la touche a été relachée


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2002 à 14:07:18    

Tu peux me filer un bout de code car je ne sais pas du tout manier les champs de bits  :(

Reply

Marsh Posté le 22-07-2002 à 14:21:12    

// on appuie d'abord sur ctrl-C
PostMessage(hWnd, WM_KEYDOWN, VK_CONTROL, 0x00010001); // CTRL
PostMessage(hWnd, WM_KEYDOWN, (WPARAM)0x43, 0x00010001); // C
 
// puis on relache ctrl-C
PostMessage(hWnd, WM_KEYUP, VK_CONTROL, 0x00010001); // CTRL
PostMessage(hWnd, WM_KEYUP, (WPARAM)0x43, 0x00010001); // C
 
 
 


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2002 à 14:38:04    

Harkonnen a écrit a écrit :

// on appuie d'abord sur ctrl-C
PostMessage(hWnd, WM_KEYDOWN, VK_CONTROL, 0x00010001); // CTRL
PostMessage(hWnd, WM_KEYDOWN, (WPARAM)0x43, 0x00010001); // C
 
// puis on relache ctrl-C
PostMessage(hWnd, WM_KEYUP, VK_CONTROL, 0x00010001); // CTRL
PostMessage(hWnd, WM_KEYUP, (WPARAM)0x43, 0x00010001); // C




 
j'comprend pas bien ça... moi j'aurai converti le LPARAM en décimal
C'est de la Hexa que tu donnes là !?

Reply

Marsh Posté le 22-07-2002 à 14:43:06    

Merci pour ce cours sur le champ de bits, ça devient plus clair désormais !
Mais alors quel bug !!! Je met ce code dans la fonction callback à la place de WM_CLOSE :
 
PostMessage(hWnd,WM_KEYDOWN,VK_CONTROL,128L);
PostMessage(hWnd,WM_KEYDOWN,'c',0L);
 
ou :
 
PostMessage(hWnd,WM_KEYUP,VK_CONTROL,128L);
PostMessage(hWnd,WM_KEYUP,'c',0L);
 
ou les 2, et là y a le PC qui se met à beeper comme un fou et il faut faire un reset !
Enfait la console se bloque alors qu'elle est en train d'écrire le message disant qu'il faut appuyer sur Ctrl-C pour fermer donc peut être que WM_KEYUP/DOWN est trop tôt ?

Reply

Marsh Posté le 22-07-2002 à 14:46:46    

il faut mettre les 2, WM_KEYDOWN et WM_KEYUP ! tu ne peux pas en mettre qu'un !
si tu ne met que WM_KEYDOWN, ça veut dire que tu ne relaches jamais tes touches, donc le buffer se remplit et tu obtiens les effets indésirables que tu me décris


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2002 à 14:47:22    

el_gringo a écrit a écrit :

 
 
j'comprend pas bien ça... moi j'aurai converti le LPARAM en décimal
C'est de la Hexa que tu donnes là !?




Oui, c de l'hexa, peu importe que ce soit de l'hexa, décimal ou binaire


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2002 à 14:55:53    

PostMessage(hWnd,WM_KEYDOWN,VK_CONTROL,0x00010001);
PostMessage(hWnd,WM_KEYDOWN,(WPARAM)0x43,0x00010001);
 
PostMessage(hWnd,WM_KEYUP,VK_CONTROL,0x00010001);
PostMessage(hWnd,WM_KEYUP,(WPARAM)0x43,0x00010001);
 
ce code ne marche pas mais ça plante pas. Par contre toi Harko tu met 0x00010001 aussi bien à Ctrl qu'à C est-ce normal ? Alors pourquoi El Gringo met 0 & 128 et non pas les 2 mêmes nombres ?

Reply

Marsh Posté le 22-07-2002 à 15:08:37    

Je me suis planté dans les scancodes et les virual keys. essaie plutot ceci :
 
PostMessage(hwnd, WM_KEYDOWN, VK_CONTROL, 0x001D0001 ) ;
PostMessage(hwnd, WM_KEYDOWN, (WPARAM)0x43, 0x00170001 ) ;
PostMessage(hwnd, WM_KEYUP, (WPARAM)0x43, 0xC0170001 ) ;
PostMessage(hwnd, WM_KEYUP, VK_CONTROL, 0xC01D0001 ) ;


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2002 à 15:13:11    

Ca ne marche pas ! (mais ça ne plante plus c déjà ça)

Reply

Marsh Posté le 22-07-2002 à 15:34:00    

:heink:  
Essaie de voir avec Spy++ si la console reçoit bien les messages.
 
Je m'explique sur la signification de lParam :
 
0x001D 0001
les 2 octets de poids faibles indiquent le nombre de répétitions (ici 1)
les bits 16 à 23 indiquent le scancode de la touche CTRL (1D)
les autres bits sont inutiles pour un KEYDOWN
 
0xC01D 0001
les bits 30 et 31 sont mis à 1 (C0) :
- bit 30 = état précédent de la touche avant envoi du message (1 = enfoncée, ce qui était le cas)
- bit 31 = état de transition de la touche (1 = touche relachée, ce qui est le cas ici)
 
donc, ça devrait marcher.... j'ai pas testé, mais je vois pas ce qui peut merder !


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2002 à 15:36:45    

tiens, j'ai une idée : tu utilises Spy++ sur la console. tu tapes CTRL-C pour la fermer, puis tu observes les paramètres correspondants. tu envoies ensuite un WM_KEYDOWN et WM_KEYUP avec ces paramètres


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2002 à 15:56:35    

Aucun message WM_KEYDOWN/UP envoyé, tu m'étonnes que ça ne marchait pas !
il y a ça d'intéressant (après c STYLECHANGING, ACTIVATE,...) :
00000E74 P message:0x0418 [User-defined:WM_USER+24] wParam:47180000 lParam:C7A14754
 
Comment faut-il réutiliser cela ? Directement en envoyant WM_USER+24, wParam & lParam ?

Reply

Marsh Posté le 22-07-2002 à 16:02:58    

non, surtout pas, ça n'a rien à voir avec WM_KEYxxxx
il faut savoir pourquoi la console ne récupère pas ces messages. es tu sur que le hWnd de la console est correct ?
 
utilise Spy++ pour visualiser le hWnd de la console, puis fais un MessageBox pour afficher le hWnd. compare les, et vois s'ils sont identiques


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2002 à 16:11:28    

Je crois qu'on c mal compris : le message que je t'ai donné dans le post précédent c'est ce que Spy++ reçoit quand je fais à la main Ctrl+C.
 
Sinon je ne vois pas comment comparer les hwnd. Comment faire, c quoi un hWnd, c'est pas un entier, c quoi ? Je vois pas quoi afficher dans la msgbox. Le hwnd dans spy++ c ce qui est appelé Window ?

Reply

Marsh Posté le 22-07-2002 à 16:26:20    

Et puis j'y pense c sur que c le bon hWnd puisque le message WM_CLOSE marche (sauf qu'il y a cette foutue popup qui oblige à laisser tomber WM_CLOSE)

Reply

Marsh Posté le 22-07-2002 à 16:36:58    

peut etre que le hWnd de la popup est différent de celui de la console, ce qui ne m'étonnerait pas d'ailleurs, car la console est incapable d'afficher du graphisme.
 
utilise Spy++ sur le popup et la console, et voit si les hwnd sont différents


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2002 à 16:43:00    

En effet les hwnd sont différents. Lorsque que je veux voir les messages de la console et non de la popup de la console, voila le message me disant que c impossible... :
 
The specified window cannot be spied upon. Windows will not allow access to the message stream for this window.
 
De mieux en mieux lol...

Reply

Marsh Posté le 22-07-2002 à 16:47:26    

ben t'as plus qu'a faire un EnumWindows pour récuperer la fenetre popup, et envoyer ensuite les messages que je t'ai indiqués plus haut.
ça devrait le faire :)


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2002 à 16:50:29    

Ok merci.
Peux tu m'expliquer comment se servir des hWnd (les comparer). Comment vais-je faire avec mes enum windows pour savoir quelle est la bonne fenêtre ?

Reply

Marsh Posté le 22-07-2002 à 16:59:22    

HWND h = ::FindWindow("ttyGrab","" ); ne marche pas, rien n'est trouvé. Pourtant la class de la console (et non la popup de la console) est bien ttyGrab d'après Spy++ et son title ""... :sweat:

Reply

Marsh Posté le 22-07-2002 à 17:02:54    

antsite a écrit a écrit :

Ok merci.
Peux tu m'expliquer comment se servir des hWnd (les comparer). Comment vais-je faire avec mes enum windows pour savoir quelle est la bonne fenêtre ?




tu as fait dans ton post suivant ce que je t'aurais siggéré :)


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le 22-07-2002 à 17:06:09    

antsite a écrit a écrit :

HWND h = ::FindWindow("ttyGrab","" ); ne marche pas, rien n'est trouvé. Pourtant la class de la console (et non la popup de la console) est bien ttyGrab d'après Spy++ et son title ""... :sweat:  




et si tu renseignes également le second paramètre de FindWindow (le nom de la fenêtre), il ne te trouves rien ?


---------------
J'ai un string dans l'array (Paris Hilton)
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed