PenProcess Lib "kernel32"

rzmitri Messages postés 11 Date d'inscription mercredi 16 mars 2005 Statut Membre Dernière intervention 4 janvier 2008 - 3 janv. 2008 à 15:02
rzmitri Messages postés 11 Date d'inscription mercredi 16 mars 2005 Statut Membre Dernière intervention 4 janvier 2008 - 4 janv. 2008 à 21:02
Bonjour,

J'utilise ce bout que j'ai trouvé quelque part pour lancer des batch file sur plusieurs ordinateur en même temps:
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessID As Long) As Long
Private Const SYNCHRONIZE = &H100000
Private Const WAIT_TIMEOUT = &H102&

Function burn_it(machine_name As String) As Boolean

Démarre = Shell("C:" + machine_name + "_batch.bat", vbNormalFocus)
        ProcessHandle = OpenProcess(SYNCHRONIZE, False, Démarre)
        retour = WaitForSingleObject(ProcessHandle, 1)
       
        Do While retour = WAIT_TIMEOUT
            retour = WaitForSingleObject(ProcessHandle, 1)
            DoEvents
        Loop
        retour = CloseHandle(ProcessHandle)
strmsgbox = LireFichier(machine_name)
Debug.Print strmsgbox
End Function

La fonction LireFichier récupère les fichiers texte qui sont crées sur les machines distante à la fin de l'exécution de chaque batch et lit le test contenu dans ce fichier.

L'ennui est que la lecture des fichiers text ne se fait que lorsque tous les batchs sur toutes les machines aient terminé.

J'aimerai que la lecture du fichier text se fasse à la fin de chaque batch

Une idée sur comment faire ?

Merci d'avance pour votre aide

22 réponses

Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
3 janv. 2008 à 15:08
là, tu lit le fichier dès queton bat a terminé de s'executer... je vois pas de soucis...
0
rzmitri Messages postés 11 Date d'inscription mercredi 16 mars 2005 Statut Membre Dernière intervention 4 janvier 2008
3 janv. 2008 à 15:48
justement, ça marche bien lorsque je lance la fonction une seule fois mais quand je la lance plusieurs fois la lecture des fichiers ne se fait qu'à la fin de l'exécution du dernier .bat...
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
3 janv. 2008 à 15:51
comment as tu constaté cela ?
as tu inséré un point d'arret ?
0
rzmitri Messages postés 11 Date d'inscription mercredi 16 mars 2005 Statut Membre Dernière intervention 4 janvier 2008
3 janv. 2008 à 15:58
les debug.print se font tous en même temps quand le dernier .bat se termine d'exécuter
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
3 janv. 2008 à 16:02
ton bat se lance rapidement ou pas ?

tentes un Debug.Print Now, strmsgbox

ca d'indiquera l'heure...

en tous cas, ta boucle est étrange...
tentes :


Do
retour = WaitForSingleObject(ProcessHandle, 1)
DoEvents
Loop While retour = WAIT_TIMEOUT
0
rzmitri Messages postés 11 Date d'inscription mercredi 16 mars 2005 Statut Membre Dernière intervention 4 janvier 2008
3 janv. 2008 à 16:10
les .bat se lancent très rapidement, les debug donnent tous la même heure, même avec ta boucle
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
3 janv. 2008 à 16:18
s'ils se lancent rapidement, tu as peut etre l'impression que tout s'ecrit une fois pour toute a la fin.
pourtant, c'est impossible.

ajoutes un point d'arret après le Debug.Print, tu verras bien
0
rzmitri Messages postés 11 Date d'inscription mercredi 16 mars 2005 Statut Membre Dernière intervention 4 janvier 2008
3 janv. 2008 à 16:30
Ils se lancent rapidment par contre l'exécution prend quelques secondes (environ 10 à 20) et les debug ne commencent qu'à la fin.
Si je mets un point d'arrêt il y a un seul debug qui se fait, les autres après continuation se font avec l'heure de la réexécution.

Je t'explique un peu comment ça marche: j'ai un formulaire avec 5 boutons, chaque bouton lance la fonction avec comme paramètre le nom de la machine. Si je mets chaque bouton dans une form à part, ça fonctionne parfaitement !
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
3 janv. 2008 à 16:33
ok.
Ajoutes

Option Explicit tout en haut de ton module
et déclare tes variables
0
rzmitri Messages postés 11 Date d'inscription mercredi 16 mars 2005 Statut Membre Dernière intervention 4 janvier 2008
3 janv. 2008 à 16:46
ça n'a rien changé
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
3 janv. 2008 à 16:48
qu'a tu, maintenant, comme code ?
0
rzmitri Messages postés 11 Date d'inscription mercredi 16 mars 2005 Statut Membre Dernière intervention 4 janvier 2008
3 janv. 2008 à 16:57
Voici tout le code en question:

Option Compare Database
Option Explicit


Rem declaration des api qui permettent d'attendre la fin de l'execution avant de passer a autre chose
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessID As Long) As Long
Private Const SYNCHRONIZE = &H100000
Private Const WAIT_TIMEOUT = &H102&


Function Copy_it(machine_name As String) As String
Dim strmsgbox As String
Dim Démarre, ProcessHandle, retour


 Démarre = Shell("C:" + machine_name + "_batch.bat", vbNormalFocus)
        ProcessHandle = OpenProcess(SYNCHRONIZE, False, Démarre)
        retour = WaitForSingleObject(ProcessHandle, 1)
       
        Do
        retour = WaitForSingleObject(ProcessHandle, 1)
            DoEvents
        Loop While retour = WAIT_TIMEOUT
       
        retour = CloseHandle(ProcessHandle)
         strmsgbox = LireFichier(machine_name)
      Copy_it = strmsgbox
Debug.Print Now, machine_name & ": " & Copy_it


End Function




Function LireFichier(machine_name As String) As String
    Dim fso     As FileSystemObject
    Dim fFile   As File
    Dim ts      As TextStream
    Dim sPath, result As String
   
    sPath = "\" & machine_name & "" & "c$" & machine_name & "_log.txt"
    Set fso = CreateObject("Scripting.FileSystemObject")
   
    If fso.FileExists(sPath) = False Then
        Exit Function
    End If
   
    Set fFile = fso.GetFile(sPath)
    Set ts = fFile.OpenAsTextStream(ForReading)
  
    result = Trim(ts.ReadAll)
   
    ts.Close
    Set ts = Nothing
    Set fFile = Nothing
    Set fso = Nothing


    Debug.Print result
    LireFichier = result


End Function




 
0
rzmitri Messages postés 11 Date d'inscription mercredi 16 mars 2005 Statut Membre Dernière intervention 4 janvier 2008
3 janv. 2008 à 19:14
J'ai retesté le code avec des .bat qui prennent bcq plus de temps (entre 5 et 10 min) , à la fin du premier batch, il y a un debug qui se fait, les autres se font tous en même temps à la fin d'exécution du dernier
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
4 janv. 2008 à 09:42
coté code, rien ne laisse transparaître ce comportement, a part les DoEvents qui ne sont pas systématiquement appelés...
0
rzmitri Messages postés 11 Date d'inscription mercredi 16 mars 2005 Statut Membre Dernière intervention 4 janvier 2008
4 janv. 2008 à 10:58
Réponse reçu sur un newsgroup de Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
FAQ VB: http://faq.vb.free.fr/

C'est un peu compliqué par ce que tu veux en même temps un
fonctionnement SYNCHRONE (attendre la fin d'exécution pour lire
le batch) et ASYNCHRONE (par ce que tu lances plusieurs process).

En plus, les process eux même sont lancés de façon asynchrone
(clic sur un bouton) MAIS lancés par la même fonction...

On tourne en rond.

Je ne suis pas sur qu'il y ait une vraie solution viable sans
utiliser de vrais threads, ce qui est un cauchemard à faire
en VB (à cause de l'instabilité dans l'IDE entre autre).

Peut être que la bonne solution est de faire un lancement
asynchrone de tous les process et de récupérer les fichiers
de log par un polling.
Je pense que c'est ce que je ferais, sans connaitre toutes
tes contraintes bien sur.
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
4 janv. 2008 à 11:04
ah ! je ne savais pas que tu t'amusais a en lancer plusieurs en même temps...

normallement pas de soucis, remarque, (a part tes variables qui ne sont pas typées)
puisque bien qu'executant la même fonction plusieurs fois, les variables sont propres a la fonction....
0
rzmitri Messages postés 11 Date d'inscription mercredi 16 mars 2005 Statut Membre Dernière intervention 4 janvier 2008
4 janv. 2008 à 11:06
désolé j'ai bien compris, peux-tu m'expliquer un peu plus ce qu'il faire ? et merci encore pour ta réactivité et ton aide
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
4 janv. 2008 à 11:25
J'ai fait le test, en utilisant des fichiers BAT qui font ce genre de choses, sur divers dossiers, pour que le temps de traitement soit different :

Dir C:\Windows\system32 /s > C:\Machine_0_log.txt

J'ai testé en utilisant ton code, remanié pour la propreté de la chose:


Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessID As Long) As Long
Private Const SYNCHRONIZE = &H100000
Private Const WAIT_TIMEOUT = &H102&

Public Function Copy_it(ByRef vsMachineName As String) As String
Dim nPID As Long
Dim hProcess As Long
On Local Error Resume Next
nPID = Shell("C:" & vsMachineName & "_batch.bat", vbNormalNoFocus)
If nPID Then
hProcess = OpenProcess(SYNCHRONIZE, False, nPID)
If hProcess <> -1 Then
Do
DoEvents
Loop While WaitForSingleObject(hProcess, 200) = WAIT_TIMEOUT

CloseHandle hProcess

'Copy_it = LireFichier("\" & vsMachineName & "" & "c$" & vsMachineName & "_log.txt")
Copy_it = LireFichier("C:" & vsMachineName & "_log.txt")
Debug.Print Now, vsMachineName & ": ", Left$(Copy_it, 50)
End If
End If
End Function

Public Function LireFichier(ByRef vsPath As String) As String
Dim iFile As Integer
Dim xbData() As Byte
If Dir$(vsPath) <> vbNullString Then
iFile = FreeFile
Open vsPath For Binary Access Read As iFile
ReDim xbData(LOF(iFile))
Get iFile, , xbData
Close iFile
LireFichier = StrConv(xbData, vbUnicode)
End If
End Function

Private Sub Command1_Click(Index As Integer)
Copy_it "Machine_" & Index
End Sub


mais je n'ai pas eu de soucis....
pourtant, j'ai cliqué comme un forcené ^^
0
jmfmarques Messages postés 7666 Date d'inscription samedi 5 novembre 2005 Statut Membre Dernière intervention 22 août 2014 27
4 janv. 2008 à 11:44
Bonjour Rernfields,

C'est tout simplement parce que tout allait très vite et qu'il ne voyait que la dernière ligne...

Il a été invité à envoyer vers une textbox ===>> tout se déroule bien séquentiellement ....
Reste que l'affichage lui-même prend un peu de temps et qu'un simple doevents lui permet d'y voir plus clair...
0
Renfield Messages postés 17287 Date d'inscription mercredi 2 janvier 2002 Statut Modérateur Dernière intervention 27 septembre 2021 74
4 janv. 2008 à 12:03
ok, donc le coup du "met un breakpoint" est passé aux oubliettes ....

bref. ca fonctionne donc bien
0
Rejoignez-nous