Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Récupérer le hWnd d'un programme lancé par CreateProcess

3 réponses
Avatar
elxav
Bonjour la communauté,

Win 2000 Pro, VB6, et grand nageur dans les APIs de Windows :-(

Mon projet:
Au démarrage de mon programme VB, je souhaite
- Terminé un Programme (Ca marche)
- Lancer un autre programme et attendre qu'il se termine (Marche
presque)
- Relancer le programme terminé à la première étape

En fouinant à droite à gauche, j'ai récupéré un certain nombres de
fonctions, et suis arrivé à ce qui suit plus bas.

Je ne comprends pas pourquoi la fonction InstanceToWnd ne fonctionne
"qu'à moitié" :-(

Si je mets un point d'arrêt sur la ligne
=> If lpProcID <> 0 And lphWnd <> 0 Then

Je lance la fonction par
=> booRet = fRunApp(strProcess1RunName, strErrMsg, lnghWnd,
lngProcID, SW_NORMAL)

L'exécution s'arrête et le pointeur lphWnd vaut 0 ??!!??

Je replace le point d'exécution sur le "lphWnd =
InstanceToWnd(lpProcID)", et fait F5 pour continuer l'exécution et
cette fois lphWnd contient bien une valeur non nulle.

Des idées?

D'avance Merci.
Cordialement.

**************
Function fRunApp(Pathname As String, strErrMsg As String, lphWnd As
Long, lpProcID As Long, Optional WindowStyle As Long)
Dim proc As PROCESS_INFORMATION
Dim start As STARTUPINFO
Dim Ret As Long

' Initialize the STARTUPINFO structure:
With start
.cb = Len(start)
If Not IsMissing(WindowStyle) Then
.dwFlags = STARTF_USESHOWWINDOW
.wShowWindow = WindowStyle
End If
End With

fRunApp = False

' Start the shelled application:
Ret& = apiCreateProcessA(0&, Pathname, 0&, 0&, 1&, _
NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)

If Ret& = 1 Then
Ret& = WaitForSingleObject(proc.dwProcessID, 5000)
End If

lpProcID = proc.dwProcessID
lphWnd = InstanceToWnd(lpProcID)

If lpProcID <> 0 And lphWnd <> 0 Then
fRunApp = True
End If

Function InstanceToWnd(ByVal target_pid As Long) As Long
'Trouver le Handle d'une fenêtre à partir de l'ID d'un Process

Dim test_hwnd As Long
Dim test_pid As Long
Dim test_thread_id As Long

'Find the first window
test_hwnd = FindWindow(ByVal 0&, ByVal 0&)
Do While test_hwnd <> 0
'Check if the window isn't a child
If apiGetParent(test_hwnd) = 0 Then
'Get the window's thread
test_thread_id = GetWindowThreadProcessId(test_hwnd, test_pid)
If test_pid = target_pid Then
InstanceToWnd = test_hwnd
Exit Do
End If
End If
'retrieve the next window
test_hwnd = GetWindow(test_hwnd, GW_HWNDNEXT)
Loop
End Function

3 réponses

Avatar
Thierry Dymon
Pour la fin d'un programme, il existe deux solutions :

- Si l'on lance le programme, il suffit d'utiliser la fonction
ShellExecuteEx() en lui demandant de nous retourner un handle; et il suffira
ensuite monitorer cet handlle : tant qu'il est valide, l'application
fonctionne toujours. Pour un exemple concret :
http://cfrofro.free.fr/OFC_CL_2_OFX.htm
- Sinon il suffit d'ouvrir un handle en partant du dwProcessid.

Pour la fenêtre, je n'ai pas décortiqué, mais sache que j'ai une application
qui recherche la fenêtre d'une boite dos, et que selon l'OS (w9x ou nt),
j'ai plus ou moins de fenêtres mais seule une des fenêtres est valide (elle
a un titre). Il procéde en demandant une énumération des fenêtres.
Avatar
Zoury
Salut!

regarde ce site, tu y trouveras ce que tu cherches.. voici un exemple en
particulier qui pourrait t'intéresser :
http://vbnet.mvps.org/code/faq/waitforsingleobject2.htm



--
Cordialement
Yanick Lefebvre
MVP pour Visual Basic
"ElXav" a écrit dans le message de
news:
Bonjour la communauté,

Win 2000 Pro, VB6, et grand nageur dans les APIs de Windows :-(

Mon projet:
Au démarrage de mon programme VB, je souhaite
- Terminé un Programme (Ca marche)
- Lancer un autre programme et attendre qu'il se termine (Marche
presque)
- Relancer le programme terminé à la première étape

En fouinant à droite à gauche, j'ai récupéré un certain nombres de
fonctions, et suis arrivé à ce qui suit plus bas.

Je ne comprends pas pourquoi la fonction InstanceToWnd ne fonctionne
"qu'à moitié" :-(

Si je mets un point d'arrêt sur la ligne
=> If lpProcID <> 0 And lphWnd <> 0 Then

Je lance la fonction par
=> booRet = fRunApp(strProcess1RunName, strErrMsg, lnghWnd,
lngProcID, SW_NORMAL)

L'exécution s'arrête et le pointeur lphWnd vaut 0 ??!!??

Je replace le point d'exécution sur le "lphWnd > InstanceToWnd(lpProcID)", et fait F5 pour continuer l'exécution et
cette fois lphWnd contient bien une valeur non nulle.

Des idées?

D'avance Merci.
Cordialement.

**************
Function fRunApp(Pathname As String, strErrMsg As String, lphWnd As
Long, lpProcID As Long, Optional WindowStyle As Long)
Dim proc As PROCESS_INFORMATION
Dim start As STARTUPINFO
Dim Ret As Long

' Initialize the STARTUPINFO structure:
With start
.cb = Len(start)
If Not IsMissing(WindowStyle) Then
.dwFlags = STARTF_USESHOWWINDOW
.wShowWindow = WindowStyle
End If
End With

fRunApp = False

' Start the shelled application:
Ret& = apiCreateProcessA(0&, Pathname, 0&, 0&, 1&, _
NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)

If Ret& = 1 Then
Ret& = WaitForSingleObject(proc.dwProcessID, 5000)
End If

lpProcID = proc.dwProcessID
lphWnd = InstanceToWnd(lpProcID)

If lpProcID <> 0 And lphWnd <> 0 Then
fRunApp = True
End If

Function InstanceToWnd(ByVal target_pid As Long) As Long
'Trouver le Handle d'une fenêtre à partir de l'ID d'un Process

Dim test_hwnd As Long
Dim test_pid As Long
Dim test_thread_id As Long

'Find the first window
test_hwnd = FindWindow(ByVal 0&, ByVal 0&)
Do While test_hwnd <> 0
'Check if the window isn't a child
If apiGetParent(test_hwnd) = 0 Then
'Get the window's thread
test_thread_id = GetWindowThreadProcessId(test_hwnd, test_pid)
If test_pid = target_pid Then
InstanceToWnd = test_hwnd
Exit Do
End If
End If
'retrieve the next window
test_hwnd = GetWindow(test_hwnd, GW_HWNDNEXT)
Loop
End Function


Avatar
elxav
Bonjour Thierry, bonjour Yanick,

Je parviens bien à lancer un programme et à attendre qu'il se termine.
J'ai juste un soucis pour récupérer le handle de la fenêtre de l'appli
ainsi lancée.
J'ai contourné le problème en bouclant sur la fonction InstanceToWnd

lphWnd = 0
While lphWnd = 0
lphWnd = InstanceToWnd(lpProcID)
Wend

Je peux avoir à lancer un programme, sans attendre qu'il se termine.
C'est pourquoi, j'ai besoin du hWnd du Process pour gérer la fenêtre
depuis mon appli.

Merci quand même pour vos infos.
Je vais essayer avec Shell ou ShellExecute au lieu de
CreateProcessA...

A bientôt.
Xav.