Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Tester l'exécution d'un script

263 views
Skip to first unread message

SupDePlouf

unread,
Oct 3, 2006, 4:55:02 AM10/3/06
to
Bonjour,

Comment tester dans un script batch qu'un auture script batch est en cours
d'exécution ou non ?

Merci
--
SupDePlouf

Gilles LAURENT

unread,
Oct 3, 2006, 7:14:57 AM10/3/06
to
"SupDePlouf" <SupDe...@discussions.microsoft.com> a écrit dans le
message de news:DA3F61D7-3933-4BCC...@microsoft.com
| Bonjour,

Bonjour,

| Comment tester dans un script batch qu'un auture script batch est en
| cours d'exécution ou non ?

Ci-dessous le script VBScript 'isRunning.vbs" permettant de déterminer
si un script batch (*.cmd ou *.bat) est en cours d'exécution.

+++ Usage
\>cscript isRunning.vbs <nom_du_script_batch>

+++ Exemple
\>cscript isRunning.vbs toto.bat

Note : La variable d'environnement errorlevel est fixée comme suit :
%errorlevel% = 0 si le script batch n'est pas en cours d'exécution
%errorlevel% = 1 si le script batch est en cours d'exécution

Pour tester dans un script batch si le script toto.bat est en cours
d'exécution
cscript //nologo isRunning.vbs toto.bat || echo en cours d'exécution

--- Coupez ici : isRunning.vbs ---

Option Explicit

' déclaration des variables
Dim oWMI, oProc
Dim colProcs
Dim strBatch

' lecture du nom du script batch
strBatch = WScript.Arguments (0)

' initialisation des objets
Set oWMI = GetObject ("winmgmts:\\.\root\cimv2")
Set colProcs = oWMI.ExecQuery ( _
"Select * From Win32_Process " & _
"Where Name='cmd.exe'")

' énumération des processus console actifs
For Each oProc in colProcs
If InStr ( _
LCase (oProc.CommandLine), _
LCase (strBatch)) _
Then
WScript.Quit (1)
End If
Next

--- Coupez ici : isRunning.vbs ---

--
Gilles LAURENT
Me contacter : http://cerbermail.com/?zoTY7ZkLcD


Jacques Barathon [MS]

unread,
Oct 3, 2006, 10:19:30 PM10/3/06
to
Gilles,

Ta solution marche super bien si le script batch a été lancé depuis
l'Explorateur. Si en revanche il a été lancé depuis l'invite de commandes
elle-même, la propriété CommandLine ne contiendra que la référence à
cmd.exe.

On peut quand même tester ce cas particulier en s'appuyant sur le titre de
la fenêtre. Si une commande est lancée depuis l'invite de commandes, le nom
de la commande apparaît dans la barre de titre. Et l'information est
accessible depuis l'objet .Net System.Diagnostics.Process, qui expose
l'information par sa propriété MainWindowTitle. On pourra donc écrire (en
PowerShell pour rester dans un langage qui permet l'accès à WMI et aux
objets .NET dans la plus simple évidence) ;-) :

function test-script ($scriptname="toto.bat")
{
$cmd = get-wmiobject win32_process -filter 'Name="cmd.exe"'
$cmd | where {$_.commandline -match $scriptname -or (get-process -id
$_.Handle).MainWindowTitle -match $scriptname}
}

Exemple:
PS> test-script loop.bat | format-table name,handle,commandline -a

name handle commandline
---- ------ -----------
cmd.exe 3496 "D:\Windows\system32\cmd.exe"
cmd.exe 6408 cmd /c ""C:\Documents and Settings\jbaratho\My
Documents\Private\test\loop.bat" "

Le premier process (id 3496) a cmd.exe en CommandLine. Le script loop.bat a
donc été lancé depuis cmd.exe.
Le second process (id 6408) a "cmd /c ...\loop.bat" en CommandLine. Le
script a donc été directement lancé depuis l'Explorateur (ou toute autre
application permettant d'invoquer un autre exécutable).

Jacques

"Gilles LAURENT" <gl...@free.fr> a écrit dans le message de news:
OgSGz1t5...@TK2MSFTNGP05.phx.gbl...

Méta-MCI

unread,
Oct 3, 2006, 6:08:49 PM10/3/06
to
Bonsoir !


Cela dépend comment a été lancé le batch.

S'il a été lancé interactivement, il n'est pas possible de savoir,
simplement, si le batch est en fonctionnement.

S'il a été lancé comme paramètre d'une ligne de commande (par exemple, avec
un "cmd /ctemp.bat"), là, c'est possible.
Il suffit d'utiliser un batch de ce genre :
wmic process where name="cmd.exe" list full |find "temp.bat"

En l'absence du nom du script dans la ligne de commande, il reste possible
de lister tous les process "cmd.exe" (comme le fait Gilles), avec le
mini-batch suivant :
wmic process where name="cmd.exe" list full |find "CommandLine"
(pour avoir la ligne de commande)

ou
wmic process where name="cmd.exe" list full |find "ProcessId"
(pour avoir le PID)

Mais je doute que cela réponde à ton besoin.

Une autre solution consiste à utiliser un signal, dans le premier batch (par
exemple un fichier-repère), ouvert au début du batch, et supprimé à la fin.
Si le signal existe, c'est que le batch est lancé.
Mais, il faut avoir la possibilité de modifier le batch...

@-salutations

Michel Claveau


XX.mcXX@xmxclaveauxx.xx.com Michel Claveau

unread,
Oct 4, 2006, 2:40:41 AM10/4/06
to
Bonjour, Jacques !

Normalement, ce sont les vampires qui travaillent de nuit.
A moins que les microsoftiens...

Sinon, l'idée du titre de la fenêtre est intéressante, avec PowerShell,
qui expose cette propriété. Ce qui n'est pas le cas de wmic (ou alors,
je n'ai pas trouvé).

--
@-salutations

Michel Claveau


XX.mcXX@xmxclaveauxx.xx.com Michel Claveau

unread,
Oct 4, 2006, 2:54:11 AM10/4/06
to
Re

à la réflexion, il n'existe aucune méthode fiable, pour savoir si un
batch est en cours.

Pour les raisons suivantes :
- fondamentalement, un batch n'est qu'un pointeur sur un fichier, qui
est ouvert/fermé à chaque appel. On le voit, car le fichier est
modifiable pendant l'exécution.
- un batch peut modifier le titre courant de la fenêtre
(title=XXX...)
- un batch peut être lancé de multiple façons, y compris de manière
invisible (sans fenêtre), et windows ne voit pas toujours la même chose
- lorsqu'un batch appelle une commande externe, cela crée (le plus
souvent) un nouveau process, dont on n'a pas forcément la dépendance.
Et cela vaut pour des batch qui appelent d'autres batch. Résultat : il
y a des situations d'où on ne pourra pas sortir d'informations fiables.

Conclusion : si on veut qu'un batch soit "traçable", il faut prévoir ça
à l'intérieur du batch lui-même.

--
@-salutations

Michel Claveau


Jean

unread,
Oct 4, 2006, 3:09:09 AM10/4/06
to
> Conclusion : si on veut qu'un batch soit "traçable", il faut prévoir ça à
> l'intérieur du batch lui-même.

Absolument :-)

Amicalement,

--
Jean - JMST
Belgium


Jacques Barathon [MS]

unread,
Oct 4, 2006, 5:24:05 AM10/4/06
to
"Michel Claveau" <Enleverles XX....@XmXclaveauXX.XX.com> a écrit dans le
message de news: mn.22077d6a2...@XmXclaveauXX.XX.com...

> Bonjour, Jacques !
>
> Normalement, ce sont les vampires qui travaillent de nuit.
> A moins que les microsoftiens...

Oh, je ne travaillais pas, juste une petite crise d'insomnie :-(

> Sinon, l'idée du titre de la fenêtre est intéressante, avec PowerShell,
> qui expose cette propriété. Ce qui n'est pas le cas de wmic (ou alors, je
> n'ai pas trouvé).

En l'occurrence PowerShell exploite la propriété MainWindowTitle de la
classe .NET System.Diagnostics.Process. Il se trouve que WMI expose la ligne
de commande mais pas le titre de la fenêtre, et que .NET expose le titre de
la fenêtre mais pas la ligne de commande. Heureusement, PowerShell est
arrivé, qui a accès aux deux mondes! :-)

Sinon, sur le fond tu as entièrement raison à propos de la traçabilité d'un
batch. Avant de voir la réponse de Gilles j'étais d'ailleurs parti pour
répondre avec une solution basée sur ce principe de fichier-repère. Je m'en
suis servi très souvent dans des tâches automatisées sur des serveurs. Ce
mécanisme est très simple et peut permettre à peu près tous les types de
synchronisation souhaités.

Jacques

Gilles LAURENT

unread,
Oct 5, 2006, 10:11:11 AM10/5/06
to
"Jacques Barathon [MS]" <jbar...@online.microsoft.com> a écrit dans le
message de news:e8zUab5...@TK2MSFTNGP02.phx.gbl

Bonjour,

[...]

| Sinon, sur le fond tu as entièrement raison à propos de la
| traçabilité d'un batch. Avant de voir la réponse de Gilles j'étais
| d'ailleurs parti pour répondre avec une solution basée sur ce
| principe de fichier-repère. Je m'en suis servi très souvent dans des
| tâches automatisées sur des serveurs. Ce mécanisme est très simple et
| peut permettre à peu près tous les types de synchronisation souhaités.

C'est vrai que s'appuyer sur les arguments de la ligne de commande du
processus cmd.exe pour tester l'exécution d'un script batch n'est pas
fiable à 100%. Néanmoins, je pense que dans la majorité des scénarii
cette technique peut être adoptée. Toutefois, une solution plus robuste
serait de démarrer le batch à surveiller dans un job. De ce fait, quoi
que fasse le script batch (commandes externes, appels à d'autres scripts
batch etc ...) l'environnement d'exécution serait limité au job. Pour
tester l'éxécution du script batch et/ou de ses dépendances il suffirait
simplement de vérifier la présence du job car le job n'existerait que
pendant le temps d'exécution du batch et de ses dépendances. A vrai dire
j'ai maquetté avec succès et cela donne le résultat suivant :

+++ Usage

Pour exécuter un script batch ou un processus dans un job
Si le job n'existe pas il est créé
\>job3_14.exe -run <commande> -jobname <nom_du_job>

Pour vérifier la présence du job
\>job3_14.exe -status -jobname <nom_du_job>

Pour lister les processus en cours d'exécution dans le job
Affichage du pid et du nom du processus
\>job3_14.exe -query -jobname <nom_du_job>

Pour attendre jusqu'à la fin du job
\>job3_14.exe -wait -jobname <nom_du_job>

Pour terminer le job donc arrêter tous les processus membres
\>job3_14.exe -kill -jobname <nom_du_job>

J'ai écrit le binaire CUI job3_14.exe en C. Il serait tout à fait
envisageable de l'implémenter sous forme d'un ActiveX ou serveur COM ;-)
dans le but d'utiliser ces méthodes et propriétés à partir de VBScript
ou tout autre langage supportant automation. Cela pourrait donner cela :

--- script1.vbs : démarrage des batch ---

Option Explicit

' déclaration des variables
Dim oJob

' initialisation des objets
Set oJob = CreateObject ("IJob3_14.job")

' définition du nom du job
oJob.Name = "monJob"

' création du job et exécution des processus
oJob.Run "test1.bat" ' création du job puis démarrage du processus
oJob.Run "test2.bat" ' démarrage du processus dans le job

' attente de la fin du traitement
oJob.Wait

--- script1.vbs : démarrage des batch ---

--- script2.vbs : contrôle du job ---

Option Explicit

' déclaration des variables
Dim oJob, oProc
Dim colProc

' initialisation des objets
Set oJob = CreateObject ("IJob.job")

' définition du nom du job à contrôler
oJob.Name = "monJob"

' attente de la fin du job
Do Until oJob.Status = 0

' lecture des processus présents dans le job
Set colProc = oJob.Query
For Each oProc In colProc
WScript.Echo oProc.ProcessId
WScript.Echo oProc.ProcessName
Next

' pause
WScript.Sleep (1000)
Loop

' job terminé
WScript.Echo "Done..."

--- script2.vbs : contrôle du job ---

MC

unread,
Oct 5, 2006, 11:32:09 AM10/5/06
to
Bonjour !

Mais, si le batch en appelle un autre (directement, ou par CALL), ça ne
suivra pas.

--
@-salutations

Michel Claveau


Gilles LAURENT

unread,
Oct 5, 2006, 1:21:17 PM10/5/06
to
"MC" <XX....@XX.XmclaveauX.com> a écrit dans le message de
news:mn.2c1c7d6ae...@XX.XmclaveauX.com
| Bonjour !

Bonjour,

| Mais, si le batch en appelle un autre (directement, ou par CALL), ça
| ne suivra pas.

Oui ça "suivra". C'est justement là tout l'intérêt du job. Le premier
processus est "injecté" dans le job (une enveloppe en quelque sorte) et
les descendants tournent dans ce même job. Le job est détruit de manière
implicite lorsque tous les processus membres du job sont terminés ou
alors de manière explicite en forçant sa fermeture. Dans ce dernier cas,
tous les processus en cours d'exécution seront également détruits.

Par exemple, soit le batch root.cmd

--- root.cmd ---

:: démarrage du batch root.cmd
:: cmd.exe dans le job
@echo off

:: démarrage d'un processus
:: cmd.exe et notepad.exe dans le job
start notepad.exe

:: appel d'un batch par call (test1.cmd rend la main)
:: pas de création de nouveau processus
:: cmd.exe et notepad.exe dans le job
call test1.cmd

:: démarrage d'un processus
:: cmd.exe, notepad.exe et calc.exe dans le job
start calc.exe

:: démarrage d'un processus
:: 2 cmd.exe, notepad.exe et calc.exe dans le job
start test2.cmd

:: enchaînement sur test3.cmd
:: pas de création de nouveau processus
:: 2 cmd.exe, notepad.exe et calc.exe dans le job
test3.cmd

:: lorsque le batch test3.cmd sera terminé
:: 1 cmd.exe, notepad.exe et calc.exe dans le job

--- root.cmd ---

Le job sera détruit implicitement lorsque les processus ...

cmd.exe (test2.cmd)
notepad.exe
calc.exe

... seront terminés

Méta-MCI

unread,
Oct 6, 2006, 2:45:32 AM10/6/06
to
Salut !

Il y a un truc qui m'échappe...

Je prend un exemple. J'ai différents batchs, lancés, soit manuellement, soit
par des tâches planifiées, soit par d'autres évènements.
Appelons-les test1.bat, test2.bat, test3.bat, etc.

D'après ton système, ces batchs seront lancés, chacun, dans un job
différent.

Par ailleurs, j'ai des batch de service, pour des opérations de
synchronisation, sauvegarde, archivage, documentation. Appelons-les s1.bat,
s2.bat, s3.bat, sauvegarde.bat, etc.

Les batchs testX.bat peuvent, si certaines conditions sont remplies (par
exemple, le 1er jour du mois), appeler des batchs sX.bat ; le plus souvent
par des CALL sX.bat, mais, cela arrive aussi, directement: sX.bat


Si je cherche à savoir, dans le batch test2.bat, si le batch sauvegarde.bat
est en cours d'exécution, j'ai peur de ne pas avoir la bonne réponse (par
exemple, s'il a été lancé par test1.bat, avec un CALL sauvegarde). En effet,
ton système gère le job associé à test1.bat, et ne verra pas sauvegarde.bat

Autres infos, inutiles, mais pour préciser les conditions d'utilisation :
Les batch de services peuvent durer de quelques secondes à plusieurs heures.
Il m'arrive souvent d'installer les batchs d'appels sur les postes, et les
batch de services sur des serveurs.
Cette structure de batchs (qui ressemble à une librairie d'utilitaires), je
l'utilise systématiquement, chez tous mes clients.


@-salutations

Michel Claveau

PS : à une époque, je m'en sortais en gérant un mutex, avec un programme
externe. Cela revenait au même qu'utiliser un fichier-repère, sauf pour la
persistance après re-boot (tout mutex étant détruit à l'extinction du
poste).
Mais, à cause du fonctionnement en réseau, je suis revenu au système du
fichier-repère, qui présente l'avantage d'être multi-poste. Cela permet à un
poste d'éviter de lancer un archivage, si un autre poste a déjà ce
traitement en cours. En plus, le fichier-repère permet de savoir à quelle
heure le batch a été lancé, et avec toutes les autres indications que l'on
aura mises dedans.


Gilles LAURENT

unread,
Oct 6, 2006, 4:41:06 AM10/6/06
to
"Méta-MCI" <enleverl...@XmclaveauX.com> a écrit dans le message de
news:%23lII8OR...@TK2MSFTNGP06.phx.gbl
| Salut !

Bonjour,

| Je prend un exemple. J'ai différents batchs, lancés, soit
| manuellement, soit par des tâches planifiées, soit par d'autres
| évènements.
| Appelons-les test1.bat, test2.bat, test3.bat, etc.
|
| D'après ton système, ces batchs seront lancés, chacun, dans un job
| différent.

Oui, si on veut être en mesure de surveiller ces trois jobs

| Si je cherche à savoir, dans le batch test2.bat, si le batch
| sauvegarde.bat est en cours d'exécution, j'ai peur de ne pas avoir la
| bonne réponse (par exemple, s'il a été lancé par test1.bat, avec un
| CALL sauvegarde). En effet, ton système gère le job associé à
| test1.bat, et ne verra pas sauvegarde.bat

Tout à fait. Ce concept ne permet pas de tracer l'exécution des batchs
mais uniquement d'être en mesure de déterminer si un job est en cours
d'exécution ou pas. Pour reprendre votre exemple, si test2.bat veut
savoir si le batch sauvegarde.bat est en cours d'exécution alors
test1.bat devra lancer sauvegarde.bat en tant que job :

+++ Exemple (non testé)

--- sauvegarde.bat ---
:: le script est lancé en tant que job
:: démarrage des sauvegardes des serveurs distants
:: parallélisation du traitement
start robocopy server1
start robocopy server2
start robocopy server3

:: le script sauvegarde.bat est terminé mais pas le job
:: les processus robocopy.exe sont en cours d'exécution
:: le job sera automatiquement détruit à la fin des sauvegardes

--- test1.bat ---
:: démarrage de sauvegarde.bat en tant que job
:: batch_sauvegarde ne fait donc pas partie du job batch_test1
:: il n'y a pas de notion de job enfant
job3_14.exe -run sauvegarde.bat -jobname batch_sauvegarde

:: on attend la fin du job (émulation du call)
job3_14.exe -wait -jobname batch_sauvegarde

--- test2.bat ---
job3_14.exe -status -jobname batch_sauvegarde || (
echo Le batch sauvegarde.bat est en cours ...
echo Attente de la fin du traitement
job3_14.exe -wait -jobname batch_sauvegarde
)

:: le job batch_sauvegarde est terminé
:: traitement des logs

| Il y a un truc qui m'échappe...

Donc pas du tout. Vous aviez bien compris le principe de fonctionnement.
L'idée était d'être en mesure de savoir si un script batch (au sens job)
était en cours d'exécution et cela, quoi que fasse le script batch
(commandes externes, processus détachés, ...)

SupDePlouf

unread,
Oct 6, 2006, 9:54:02 AM10/6/06
to
Bonjour et MERCI à tous

Je me permets de vous préciser un peu les choses...

En fait, j'ai script "Kix" qui copie des fichiers depuis le répertoire Rep1
vers le répertoire Rep2.

Ce script doit imperativement tourner.

Mon idée est de tester régulièrement par une tâche planifiée que ce script
est bien en fonction et si ce n'est pas le cas, le relancer.

J'ai bien pensé à utiliser le principe des fichiers-répères mais si la
machine, ou le script, s'arrête de façon inattendue le fichier est toujours
présent et le test suivant considérera que le script tourne toujours.

J'ai fait en sorte que ce script "Kix" par l'intermédiaire d'un batch du type

--- toto.bat
kix32.exe script.kix
--- toto.bat

soit lancé à chaque démarrage de la machine.

Je souhaite me prémunir d'un arrêt inattendu en surveillant, d'une façon ou
d'une autre, que ce batch ou ce script.kix tourne bien.

Quelle est donc d'après vous la meilleure solution dans ce cas précis ?

Merci
--
SupDePlouf


"SupDePlouf" a écrit :

Jacques Barathon [MS]

unread,
Oct 6, 2006, 9:32:47 PM10/6/06
to
"SupDePlouf" <SupDe...@discussions.microsoft.com> a écrit dans le message
de news: 4F2F3A53-575F-4044...@microsoft.com...
<...>

> J'ai fait en sorte que ce script "Kix" par l'intermédiaire d'un batch du
> type
>
> --- toto.bat
> kix32.exe script.kix
> --- toto.bat
>
> soit lancé à chaque démarrage de la machine.
>
> Je souhaite me prémunir d'un arrêt inattendu en surveillant, d'une façon
> ou
> d'une autre, que ce batch ou ce script.kix tourne bien.
>
> Quelle est donc d'après vous la meilleure solution dans ce cas précis ?

Je n'ai pas kix32 sur mon poste pour pouvoir tester, mais à priori la
première solution de Gilles (isRunning.vbs) devrait convenir après légère
adaptation:

Il faudrait remplacer la ligne:
"Where Name='cmd.exe'")
Par:
"Where Name="kix32.exe")

L'usage dans un batch de contrôle donnerait:

cscript //nologo isRunning script.kix || echo script.kix est toujours en
cours d'exécution.

Cela dit, le principe du fichier-repère reste valable en complément car il
peut donner des informations plus pertinentes que le fait de savoir que le
script est toujours en mémoire. Si pour une raison quelconque le script
tourne dans le vide et que les copies ne sont plus faites (par exemple à
cause d'un pb d'accès, ou d'une erreur dans un chemin), le "isRunning" ne
permettra pas de relever le problème.

Le script pourrait par exemple écrire dans un log à intervalles réguliers
et/ou à chaque étape clé, ce qui permettrait au batch de contrôle de savoir
non seulement si le script est toujours en vie mais en plus où il en est. La
solution exacte dépend étroitement de ce que fait le script (et donc de ce
qui doit être contrôlé et à quelles fréquences).

Jacques

XX.mcXX@xmxclaveauxx.xx.com Michel Claveau

unread,
Oct 8, 2006, 2:17:40 PM10/8/06
to
Bonsoir !

Je m'excuse de ne pas avoir répondu avant, mais j'ai été trop occupé.

J'ai un petit utilitaire qui permet de tester la présence d'un process
particulier, et, qui, s'il n'existe pas, lance une commande précise.

Dans les tâches planifiées, je lance régulièrement cet utiltaire
(toutes les heures, mais ça dépend de l'usage souhaité).

Je me demande si jça ne vaudrait pas le coup d'en déduire un utilitaire
plus général, de surveillance de quelques process, avec les commandes
correspondantes.

Il devrait être possible de grouper ça avec PSurv
(http://www.ponx.org/batutils), l'utilitaire de surveillance (et
d'interdiction) de process


Autre chose, tu dis utiliser Kixtart. J'ai quelques questions :
- l'aurais-tu déjà comparé à AutoIt ?
- as-tu utilisé la version dotNET de Kixtart ?
- as-tu déjà utilisé KixForms, l'extension GUI en COM ? Je l'utilise
dans certains scripts en Python, mais j'hésite à aller plus loin, ou à
choisir un autre GUI.


--
@-salutations

Michel Claveau


Gilles LAURENT

unread,
Oct 17, 2006, 12:40:18 PM10/17/06
to
Bonjour,

Après une phase de tests et de debugging, je propose aux lecteurs de ce
fil une version stable de l'outil de gestion des jobs en ligne de
commande : job3_14.exe v1.0.0.1. C'est ici :
http://glsft.free.fr/index.php?option=com_content&task=view&id=13&Itemid=28

--
Gilles LAURENT
http://glsft.free.fr
Me contacter : http://cerbermail.com/?zoTY7ZkLcD


valou75

unread,
Feb 20, 2018, 3:16:37 PM2/20/18
to
Le mercredi 04 Octobre 2006 à 00:08 par Méta-MCI :
Ca semble marcher ça:

wmic process where name="cmd.exe" GET processid, commandline

Retourne les bat en cours d'exe avec leurs nom et PID respectifs.
0 new messages