PenProcess Lib "kernel32"

Signaler
Messages postés
11
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
4 janvier 2008
-
Messages postés
11
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
4 janvier 2008
-
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
A voir également:

22 réponses

Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
68
là, tu lit le fichier dès queton bat a terminé de s'executer... je vois pas de soucis...
Messages postés
11
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
4 janvier 2008

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...
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
68
comment as tu constaté cela ?
as tu inséré un point d'arret ?
Messages postés
11
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
4 janvier 2008

les debug.print se font tous en même temps quand le dernier .bat se termine d'exécuter
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
68
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
Messages postés
11
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
4 janvier 2008

les .bat se lancent très rapidement, les debug donnent tous la même heure, même avec ta boucle
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
68
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
Messages postés
11
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
4 janvier 2008

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 !
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
68
ok.
Ajoutes

Option Explicit tout en haut de ton module
et déclare tes variables
Messages postés
11
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
4 janvier 2008

ça n'a rien changé
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
68
qu'a tu, maintenant, comme code ?
Messages postés
11
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
4 janvier 2008

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




 
Messages postés
11
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
4 janvier 2008

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
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
68
coté code, rien ne laisse transparaître ce comportement, a part les DoEvents qui ne sont pas systématiquement appelés...
Messages postés
11
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
4 janvier 2008

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.
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
68
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....
Messages postés
11
Date d'inscription
mercredi 16 mars 2005
Statut
Membre
Dernière intervention
4 janvier 2008

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
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
68
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é ^^
Messages postés
7668
Date d'inscription
samedi 5 novembre 2005
Statut
Membre
Dernière intervention
22 août 2014
26
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...
Messages postés
17286
Date d'inscription
mercredi 2 janvier 2002
Statut
Modérateur
Dernière intervention
23 décembre 2019
68
ok, donc le coup du "met un breakpoint" est passé aux oubliettes ....

bref. ca fonctionne donc bien