31 votes

Niveau d'erreur dans une boucle Pour (lot Windows)

J'ai le code batch Windows suivant :

for %%i in (iidbms iigcc iigcd dmfacp dmfrcp rmcmd qwerty) do (
  tasklist | findstr /i %%i
  echo %errorlevel%
  if %errorlevel% == 0 (echo %%i ok process found %errorlevel%)
  if %errorlevel% == 1 (echo %%i no process found %errorlevel%)
)

Mais cela ne fonctionne pas comme je m'y attends.

Tous les processus nommés iidbms, iigcc, iigcd, dmfacp, dmfrcp, rmcmd sont réels, et ils sont trouvés, tandis que qwerty est inventé et ne devrait pas être trouvé, donc devrait afficher "no process found 1", mais ce n'est pas le cas, il affiche toujours 0.

Cependant, j'ai remarqué que si je lance tasklist | findstr /i qwerty depuis l'invite de commandes DOS, juste après cela, le %errorlevel% est égal à 1.

Quelle sorte de réponse pourrait être ou est meilleure ?

42voto

Tim Abell Points 2301

Ajoutez

setlocal EnableDelayedExpansion

au début de votre script, puis utilisez !errorlevel! au lieu de %errorlevel%

Delayed Expansion fera en sorte que les variables soient développées au moment de l'exécution plutôt qu'au moment de l'analyse

~ http://ss64.com/nt/delayedexpansion.html

La réponse à une autre question qui m'a orienté dans la bonne direction:
Errorlevel of command executed by batch for loop

33voto

JRL Points 36674

IF ERRORLEVEL renvoie TRUE si le code de retour était égal ou supérieur au niveau d'erreur spécifié. Dans votre exemple, puisque 0 est inférieur à 1, la première instruction errorlevel sera toujours vraie si le code d'erreur réel est de 0 ou plus. Ce que vous voulez, c'est tester d'abord pour errorlevel 1.

Par exemple:

for %%i dans (iidbms iigcc iigcd dmfacp dmfrcp rmcmd qwerty) do (
    tasklist | findstr /i %%i
    if errorlevel 0 if not errorlevel 1 echo process
    if errorlevel 1 if not errorlevel 2 echo process non trouvé
)

Un autre problème est si vous souhaitez afficher l'errorlevel réel à partir de la boucle for. Étant donné que les variables sont résolues avant le début de la boucle, afficher %errorlevel% affichera toujours 0. Si vous voulez afficher la valeur au moment de l'exécution, vous devez modifier l'extrait de code comme ceci:

setlocal enabledelayedexpansion
for %%i dans (iidbms iigcc iigcd dmfacp dmfrcp rmcmd qwerty) do (
    tasklist | findstr /i %%i
    if errorlevel 0 if not errorlevel 1 echo %%i ok process found !errorlevel!
    if errorlevel 1 if not errorlevel 2 echo %%i aucun processus trouvé !errorlevel!
)

-1voto

ghostdog74 Points 86060

Vous pouvez utiliser vbscript,

NumArgs = WScript.Arguments.Count
strComputer="."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process")
For Each objProcess in colProcessList
    For i=0 To NumArgs-1
        If InStr( objProcess.Name ,WScript.Arguments(i)  ) > 0 Then
            WScript.Echo "trouvé:" & WScript.Arguments(i)
        End If 
    Next 
Next

Utilisation:

C:\test>cscript //nologo test.vbs explorer spool svchost
trouvé:svchost
trouvé:svchost
trouvé:svchost
trouvé:svchost
trouvé:svchost
trouvé:explorer
trouvé:svchost
trouvé:spool

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X