Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
2583 connectés 

  FORUM HardWare.fr
  Programmation
  Divers

  [Api Win32] CreateProcess / WaitForInputIdle / PostMessage

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

[Api Win32] CreateProcess / WaitForInputIdle / PostMessage

n°1505296
Evadream -​jbd-
Posté le 20-01-2007 à 11:26:14  profilanswer
 

Hello tout le monde !
 
Je fais mes premiers pas dans la manipulation de l'API Windows, et je n'arrive pas à expliquer un résultat que j'obtiens.
 
Le but de la manoeuvre est :
1 - lancer un process via la fonction CreateProcess
2 - attendre que le processus crée soit prêt via la fonction WaitForInputIdle
3 - envoyer un message via PostMessage
 
Ce mécanisme semble correctement fonctionner, mais j'ai l'impression que ça dépend des processus et de la charge de la machine.
Avec le notepad, pas de problème, mais avec d'autres applications, un temps mort de 2 secondes (grouik) est nécessaire.
 
Voilà un petit bout de code fait rapidement en python pour illuster le problème.
Ici, je lance le notepad et j'envoie un F5 pour ajouter la date du jour dans la zone d'édition.
Ça fonctionne sans le sleep, mais pas avec toutes les applications.
 
Une idée ?
 

Code :
  1. import win32api
  2. import win32process
  3. import win32con
  4. import win32event
  5. import win32ui
  6. import time
  7. # Recuperer un pid a partir d'un hwnd
  8. def GetPidFromWindow(hwnd):
  9.      return win32process.GetWindowThreadProcessId(hwnd.GetSafeHwnd())[1]
  10. # On recupere le hwnd a partir de l'id du processus (Microsoft Technet)
  11. def GetWindowHandleFromId(pid):
  12.     """ Retrieve the Window handle (hwnd) from a pid """
  13.     # Grab the first window handle that Window's finds
  14.     tempHwnd = win32ui.FindWindow(None, None)
  15.    
  16.     # Loop until there are no more window handles
  17.     while tempHwnd is not None:
  18.         if tempHwnd.GetParent() is None:
  19.             if pid == GetPidFromWindow(tempHwnd):
  20.                 return tempHwnd
  21.         tempHwnd = tempHwnd.GetWindow(win32con.GW_HWNDNEXT)
  22.     return None
  23. # Creation du process via CreateProcess
  24. appName = None
  25. commandLine = "notepad.exe"
  26. processAttributes = None
  27. threadAttributes = None
  28. inheritHandles = False
  29. creationFlags = win32con.DETACHED_PROCESS
  30. newEnvironnement = None
  31. currentDirectory = None
  32. startupinfo = win32process.STARTUPINFO()
  33. startupinfo.dwFlags = win32process.STARTF_USESHOWWINDOW
  34. startupinfo.wShowWindow = win32con.SW_SHOWMINNOACTIVE
  35. handle, hthread, process_id, thread_id = win32process.CreateProcess(appName,
  36.                                                                     commandLine,
  37.                                                                     processAttributes,
  38.                                                                     threadAttributes,
  39.                                                                     inheritHandles,
  40.                                                                     creationFlags,
  41.                                                                     newEnvironnement,
  42.                                                                     currentDirectory,
  43.                                                                     startupinfo)
  44. # On attend que l'application soit prete
  45. ret = win32event.WaitForInputIdle(handle, win32event.INFINITE)
  46. if ret != 0:
  47.     raise SystemExit("Problem during process wait" )
  48. win32api.CloseHandle(handle)
  49. # On recupere le handle de la fenetre
  50. hwnd = GetWindowHandleFromId(process_id)
  51. # ici, hwnd est le handle sur la fenetre. On lui envoie un message
  52. # time.sleep(5)
  53. hwnd.PostMessage(win32con.WM_COMMAND, 26, 0)


 
edit: Remove trailing spaces mode on ;)


Message édité par Evadream -jbd- le 20-01-2007 à 15:56:05
mood
Publicité
Posté le 20-01-2007 à 11:26:14  profilanswer
 

n°1505345
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 20-01-2007 à 15:25:47  profilanswer
 

drapal, je teste et je regarde dans l'après midi


---------------
J'ai un string dans l'array (Paris Hilton)
n°1505366
Evadream -​jbd-
Posté le 20-01-2007 à 18:18:55  profilanswer
 

Merci, c'est très sympa =)

n°1505400
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 20-01-2007 à 21:20:06  profilanswer
 

ben j'ai testé avec quelques grosses applis (Word, Firefox, FS 2004), et ça fonctionne bien... dans ton cas, quand est-ce que le Sleep() est nécessaire ? avant d'envoyer F5, ou avant de lancer le processus ?


Message édité par Harkonnen le 20-01-2007 à 21:20:29
n°1505404
Evadream -​jbd-
Posté le 20-01-2007 à 21:31:29  profilanswer
 

Un grand merci d'avoir pris ton temps pour essayer sur différentes applications. Dans mon cas, je dois faire un sleep juste avant d'envoyer le message.  
 
L'application qui me pose un problème est un logiciel d'imagerie Kodak non disponible au téléchargement :/
 
Si tu as une idée à me suggérer pour trouver ce qui ne va pas... L'idéal sera de pouvoir espionner les messages de l'application dès son démarrage pour voir si elle reçoit ce fameux message, mais je ne sais pas comment procéder.
 
A l'heure actuelle, j'utilise winspector pour espionner ces messages sur un processus déja lancé. Il faudrait que je puisse attacher un espion à un exécutable avant son lancement.
 
Je débute vraiment dans la manipulation de l'api windows, je travaille habituellement dans un environnement Linux/Unix.
 
Encore merci en tout cas !

Message cité 1 fois
Message édité par Evadream -jbd- le 20-01-2007 à 21:32:03
n°1505414
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 20-01-2007 à 21:55:36  profilanswer
 

Evadream -jbd- a écrit :

Un grand merci d'avoir pris ton temps pour essayer sur différentes applications. Dans mon cas, je dois faire un sleep juste avant d'envoyer le message.  
 
L'application qui me pose un problème est un logiciel d'imagerie Kodak non disponible au téléchargement :/


c'est quoi exactement qui ne fonctionne pas ? ce logiciel ne reçoit pas le message, ou il ne se lance pas sauf si tu Sleep() avant ?

n°1505417
Evadream -​jbd-
Posté le 20-01-2007 à 21:58:26  profilanswer
 

J'avais mal compris ta question. Le logiciel se lance, mais ne reçoit pas le message (apparemment, puisque la fonction ne s'exécute pas) à moins que je place ce fameux sleep avant d'envoyer le message.

n°1505418
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 20-01-2007 à 21:59:27  profilanswer
 

ok, alors essaie plutot d'envoyer le message par PostMessage() au lieu de SendMessage()
 
edit: je voulais dire SendMessage() au lieu de PostMessage() [:ddr555]


Message édité par Harkonnen le 20-01-2007 à 22:01:40
n°1505419
Evadream -​jbd-
Posté le 20-01-2007 à 22:01:25  profilanswer
 

C'est ce que je fais malheureusement.  

Code :
  1. hwnd.PostMessage(win32con.WM_COMMAND, 26, 0)

n°1505420
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 20-01-2007 à 22:01:58  profilanswer
 

je viens d'éditer mon précédent message :whistle:

mood
Publicité
Posté le 20-01-2007 à 22:01:58  profilanswer
 

n°1505421
Evadream -​jbd-
Posté le 20-01-2007 à 22:02:46  profilanswer
 

Il faudrait que je fasse le test sans passer par les wrappers python afin de voir si le problème ne vient pas d'eux. Ça me semble bizarre cette histoire.

n°1505422
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 20-01-2007 à 22:03:05  profilanswer
 

et avec SendMessage, ça donne quoi ?

n°1505423
Evadream -​jbd-
Posté le 20-01-2007 à 22:03:45  profilanswer
 

Je vais taistai !

n°1505425
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 20-01-2007 à 22:04:49  profilanswer
 

t'as juste qu'à remplacer PostMessage par SendMessage, les paramètres sont les memes. en remerciant Python au passage d'etre un langage interprété, c'est tellement pratique pour faire des tests

n°1505428
Evadream -​jbd-
Posté le 20-01-2007 à 22:13:44  profilanswer
 

Même chose avec SendMessage.  
 
J'ai moi aussi testé avec des applications plus conséquentes que le notepad et ça fonctionne très bien. J'ai plus trop d'idée là.  
 
Je mets un peu de temps désolé, je bosse à distance via vnc, c'est pas terrible.  
 

n°1505429
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 20-01-2007 à 22:19:50  profilanswer
 

MP

n°1505435
Evadream -​jbd-
Posté le 20-01-2007 à 23:18:30  profilanswer
 

Des fois, je devrais réfléchir.
 
L'application doit initialiser des périphériques et dont j'ai besoin pour que ma commande s'effectue bien. Ça doit mettre un peu de temps. L'application est utilisable avant que cette initialisation se fasse, et donc je suis revenu de mon WaitForInputIdle et je poste le message dans le vent.  
 
Je suis quasiment certain qu'il s'agit de ça. L'application reçoit surement un message particulier lors de l'initialisation de ces périphériques, il faudrait que je le trouve. Une autre solution serait de tester si la commande qui m'intéresse n'est pas "grisée" dans les menus de l'application, mais je ne sais si c'est possible. Si tu as une piste, même grossière ;)
 
Hop !

Message cité 1 fois
Message édité par Evadream -jbd- le 20-01-2007 à 23:18:42
n°1505440
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 20-01-2007 à 23:37:54  profilanswer
 

Evadream -jbd- a écrit :

Des fois, je devrais réfléchir.
 
L'application doit initialiser des périphériques et dont j'ai besoin pour que ma commande s'effectue bien. Ça doit mettre un peu de temps. L'application est utilisable avant que cette initialisation se fasse, et donc je suis revenu de mon WaitForInputIdle et je poste le message dans le vent.  
 
Je suis quasiment certain qu'il s'agit de ça. L'application reçoit surement un message particulier lors de l'initialisation de ces périphériques, il faudrait que je le trouve. Une autre solution serait de tester si la commande qui m'intéresse n'est pas "grisée" dans les menus de l'application, mais je ne sais si c'est possible. Si tu as une piste, même grossière ;)
 
Hop !


Non, je ne crois pas que ce soit ça, car PostMessage() est asynchrone. Elle poste le message dans la file d'attente, et rend la main au module appelant immédiatement, laissant la WndProc de l'application récupérer le message et le traiter. Ton application a donc le temps d'initialiser ses périphériques avant de récupérer le message dans la pompe à messages.
Ce que tu peux faire pour débugger : lance ton application Kodak, utilise OllyDbg (debugger gratuit), et place un point d'arrêt sur le message WM_INIT. Regarde ensuite ce qui est effectué à l'initialisation...


---------------
J'ai un string dans l'array (Paris Hilton)
n°1505441
Evadream -​jbd-
Posté le 20-01-2007 à 23:40:55  profilanswer
 

Et moi qui était très fier de mon analyze =) Je vais essayer ce que tu me suggères !

n°1505442
Harkonnen
Modérateur
Un modo pour les bannir tous
Posté le 20-01-2007 à 23:41:56  profilanswer
 

par contre, connaissance de l'assembleur obligatoire :D

n°1505448
Evadream -​jbd-
Posté le 21-01-2007 à 00:04:51  profilanswer
 

Je craque, via vnc c'est stressant. Je n'ai que des notions en assembleur, ça risque d'être violent. L'application a l'air super bien faite par contre. Je vais voir ce que je peux faire une fois devant la machine.
 
Il n'y aurait pas moyen de lancer une application dans un espion à messages  comme spy++ ou winspector ?
 
Merci une nouvelle fois pour tes conseils !

n°1505455
Evadream -​jbd-
Posté le 21-01-2007 à 00:20:39  profilanswer
 

Harkonnen a écrit :

Non, je ne crois pas que ce soit ça, car PostMessage() est asynchrone. Elle poste le message dans la file d'attente, et rend la main au module appelant immédiatement, laissant la WndProc de l'application récupérer le message et le traiter. Ton application a donc le temps d'initialiser ses périphériques avant de récupérer le message dans la pompe à messages.


 
Peut-on imaginer que la WndProc récupère le message, le traite, mais que justement, le traitement ne fait rien puisque la fameuse fonctionnalité n'est pas encore activée ? Auquel cas, il faudrait pouvoir récupérer une éventuelle erreur j'imagine.


Message édité par Evadream -jbd- le 21-01-2007 à 00:29:12
n°1505465
Evadream -​jbd-
Posté le 21-01-2007 à 01:39:48  profilanswer
 

Autre question : y'a t'il un moyen de connaître le code de retour d'une commande ? Par exemple, j'envoie un F5 au notepad et je veux savoir si l'action liée à cette commande s'est bien déroulée.  
 
Si j'ai bien compris, comme PostMessage est asynchrone, la valeur de retour nous renseigne uniquement sur le fait que le message a été correctement posté.
 
Bonne nuit =)

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Divers

  [Api Win32] CreateProcess / WaitForInputIdle / PostMessage

 

Sujets relatifs
API Sound javaAPI REST pour un youtube like
Différence entre les HashSet et les LinkedHashSet dans l'API Java[résolu] Hook win32 voulu global...
API POI (manipulation de fichiers MS Office)[Résolu] Api win 32, quelque question de débutant....
[API Win32][desklet] integrer une fenêtre dans sur le bureau ?Win Api : comment supprimer l'enfant sans supprimer le parent ?
Java, accéder aux API windows 
Plus de sujets relatifs à : [Api Win32] CreateProcess / WaitForInputIdle / PostMessage


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR