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

OpenProcess Lib "kernel32"

5 réponses
Avatar
RZ
Bonjour

J'utilise ce code pour lancer des batch file sur plusieurs ordinateurs en
même temps.

J'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 !
L'ennui vient lorsque tous les boutons sont dans le même formulaire (ce qui
est plus logique à faire;))

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

Le problème est qu'à la fin du premier batch, il y a un debug qui se fait,
les autres ne se font tous qu'en même temps à la fin d'exécution du dernier
batch
alors que le besoin de lire le fichier généré juste après la fin de
l'exécution du batch en question

Voici le code et merci de votre aide en avance

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

5 réponses

Avatar
Jean-marc
RZ wrote:
Bonjour

J'utilise ce code pour lancer des batch file sur plusieurs
ordinateurs en même temps.

J'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 ! L'ennui vient lorsque tous les boutons sont
dans le même formulaire (ce qui est plus logique à faire;))

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

Le problème est qu'à la fin du premier batch, il y a un debug qui se
fait, les autres ne se font tous qu'en même temps à la fin
d'exécution du dernier batch
alors que le besoin de lire le fichier généré juste après la fin de
l'exécution du batch en question



Hello,

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.

Tu peux éventuellement consulter ces articles et leurs liens:
http://faq.vb.free.fr/index.php?question2
http://faq.vb.free.fr/index.php?question=7

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
FAQ VB: http://faq.vb.free.fr/
mailto: remove '_no_spam_' ;
Avatar
RZ
Merci Jean-Marc pour ces acclarations.

Peux-tu l'expliquer un peu ce que tu veux dire par polling ?


"Jean-marc" a écrit dans le message
de news: 477d3497$0$29252$
RZ wrote:
Bonjour

J'utilise ce code pour lancer des batch file sur plusieurs
ordinateurs en même temps.

J'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 ! L'ennui vient lorsque tous les boutons sont
dans le même formulaire (ce qui est plus logique à faire;))

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

Le problème est qu'à la fin du premier batch, il y a un debug qui se
fait, les autres ne se font tous qu'en même temps à la fin
d'exécution du dernier batch
alors que le besoin de lire le fichier généré juste après la fin de
l'exécution du batch en question



Hello,

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.

Tu peux éventuellement consulter ces articles et leurs liens:
http://faq.vb.free.fr/index.php?question2
http://faq.vb.free.fr/index.php?question=7

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
FAQ VB: http://faq.vb.free.fr/
mailto: remove '_no_spam_' ;






Avatar
Jean-marc
RZ wrote:
Merci Jean-Marc pour ces acclarations.

Peux-tu l'expliquer un peu ce que tu veux dire par polling ?



Hello,

Le "polling", c'est l'action de surveiller quelque chose à intervalle
régulier, par exemple quand on ne dispose pas d'un évènement pour
prévenir d'un changement.

Par exemple, on peut imaginer de surveiller un répertoire en allant
regarder la liste des fichiers qu'il contient toutes les "X" secondes
ou minutes (on parle alors d'intrvalle de polling).

Dans ton cas, tu pourrais faire en sorte que tes process marchent comme
ceci:

1. Si un fichier "fini.dat" existe, le détruire
2. Faire le boulot, et produire les résultats dans un fichier : data.log
3. Une fois que tout est fini, créer un fichier vide "fini.dat"

Maintenant dans ton appli VB, tu lances les process en ASYNCHRONE, puis
tu surveilles (pour chacun et de façon asynchrone)l'apparition d'un
fichier "fini.dat" à l'endroit du process.
Dès qu'il est la, tu sais que tu peux lire "data.log" qui contient tes
résultats. Et hop, tu en profites pour détruire ensuite "fini.dat".

Dans cet exmple, le fichier "fini.dat" est juste un marqueur qui permet
à la procédure qui fait le polling de savoir que tout est fini et qu'on peut
donc lire le fichier de résultat.

Le polling a l'énorme avantage d'être un mécanisme complétement portable,
non
dépendant d'un quelconque OS ou quoi que ce soit. L'inconvénient est que
c'est
en théorie un peu moins "propre" qu'un évènement et qu'on passe un peu de
temps
à vérifier. Mais ici, un simple test de présence de fichier effctué toutes
les
10 secondes par exemple aura un coût totalement dérisoire.

Au niveau implémentation, je serais toi, je ferais un tableau dans lequel je
garde la trace des processus que j'ai lancé. Puis j'utiliserais un simple
Timer pour aller séquentiellement regarder pour chacun des processus lancés
si il y a un fichier de résultat produit. Si oui, tu fais ce que tu as à
faire
puis tu effeces cette entrée du tableau.

A la fin, ton tableau est vide. La procédure du timer ne fera alors que
constater
que le tableau est vide et donc ne consommera pas de CPU.

Tu peux raffiner et stocker aussi la date et heure de lancement, pour
éventuellement
tenir compte du fait qu'un process distant n'a pas répondu après un certain
temps.
Tu peux alors faire un rappport ou relancer le truc, ou quoi que ce soit
d'autre
qui sera approprié. Ce type de mécanisme à pour nom générique "watch dog"
(chien de
garde).

Cordialement;

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
FAQ VB: http://faq.vb.free.fr/
mailto: remove '_no_spam_' ;
Avatar
RZ
Merci beaucoup Jean-Marc pour ta précieuse aide

Cordialement,

Richard

"Jean-marc" a écrit dans le message
de news: 477e2f07$0$22319$
RZ wrote:
Merci Jean-Marc pour ces acclarations.

Peux-tu l'expliquer un peu ce que tu veux dire par polling ?



Hello,

Le "polling", c'est l'action de surveiller quelque chose à intervalle
régulier, par exemple quand on ne dispose pas d'un évènement pour
prévenir d'un changement.

Par exemple, on peut imaginer de surveiller un répertoire en allant
regarder la liste des fichiers qu'il contient toutes les "X" secondes
ou minutes (on parle alors d'intrvalle de polling).

Dans ton cas, tu pourrais faire en sorte que tes process marchent comme
ceci:

1. Si un fichier "fini.dat" existe, le détruire
2. Faire le boulot, et produire les résultats dans un fichier : data.log
3. Une fois que tout est fini, créer un fichier vide "fini.dat"

Maintenant dans ton appli VB, tu lances les process en ASYNCHRONE, puis
tu surveilles (pour chacun et de façon asynchrone)l'apparition d'un
fichier "fini.dat" à l'endroit du process.
Dès qu'il est la, tu sais que tu peux lire "data.log" qui contient tes
résultats. Et hop, tu en profites pour détruire ensuite "fini.dat".

Dans cet exmple, le fichier "fini.dat" est juste un marqueur qui permet
à la procédure qui fait le polling de savoir que tout est fini et qu'on
peut
donc lire le fichier de résultat.

Le polling a l'énorme avantage d'être un mécanisme complétement portable,
non
dépendant d'un quelconque OS ou quoi que ce soit. L'inconvénient est que
c'est
en théorie un peu moins "propre" qu'un évènement et qu'on passe un peu de
temps
à vérifier. Mais ici, un simple test de présence de fichier effctué toutes
les
10 secondes par exemple aura un coût totalement dérisoire.

Au niveau implémentation, je serais toi, je ferais un tableau dans lequel
je
garde la trace des processus que j'ai lancé. Puis j'utiliserais un simple
Timer pour aller séquentiellement regarder pour chacun des processus
lancés
si il y a un fichier de résultat produit. Si oui, tu fais ce que tu as à
faire
puis tu effeces cette entrée du tableau.

A la fin, ton tableau est vide. La procédure du timer ne fera alors que
constater
que le tableau est vide et donc ne consommera pas de CPU.

Tu peux raffiner et stocker aussi la date et heure de lancement, pour
éventuellement
tenir compte du fait qu'un process distant n'a pas répondu après un
certain temps.
Tu peux alors faire un rappport ou relancer le truc, ou quoi que ce soit
d'autre
qui sera approprié. Ce type de mécanisme à pour nom générique "watch dog"
(chien de
garde).

Cordialement;

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
FAQ VB: http://faq.vb.free.fr/
mailto: remove '_no_spam_' ;






Avatar
Jean-marc
RZ wrote:
Merci beaucoup Jean-Marc pour ta précieuse aide

Cordialement,



Et merci à toi pour le retour :-)

--
Jean-marc Noury (jean_marc_n2)
Microsoft MVP - Visual Basic
FAQ VB: http://faq.vb.free.fr/
mailto: remove '_no_spam_' ;