Exécution d'un programme dos [les bizarreries de windows] [C++] - C++ - Programmation
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...
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 !?
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?
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é
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
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.
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...
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
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
GetExitCodeProcess(pinfo.hProcess,&ecode);
TerminateProcess(pinfo.hProcess,ecode);
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
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 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 :
|
(c du copier/coller en brute, j'éspère que ça va être lisible)
Marsh Posté le 22-07-2002 à 12:33:11
...c un extrait du mon 1er prog C(++ ?), soyez indulgents !
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).
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+
Marsh Posté le 22-07-2002 à 13:44:34
Tout à fait mais j'ignore comment faire ce raccourci avec le paramètre voulu !
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 ?
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
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
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
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à !?
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 ?
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
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
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 ?
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 ) ;
Marsh Posté le 22-07-2002 à 15:34:00
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 !
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
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 ?
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
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 ?
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)
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
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...
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
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 ?
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 ""...
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é
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 ""... |
et si tu renseignes également le second paramètre de FindWindow (le nom de la fenêtre), il ne te trouves rien ?
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