Уровень ошибок в цикле For (пакетные окна) - PullRequest
22 голосов
/ 15 октября 2010

У меня есть следующий код пакета Windows:

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%)
)

Но это не работает, как я ожидаю.

Все процессы имен iidbms , iigcc , iigcd , dmfacp , dmfrcp , rmcmd являются реальными, и они найдены, вместо этого qwerty является выдуманным и не должен его искать, поэтому должен вывести "процесс не найден 1" , но это не так т, он всегда печатает 0.

Но я заметил, что если я запускаю tasklist | findstr /i qwerty из командной строки dos, сразу после этого %errorlevel% = 1.

Какой ответ может быть или лучше?

Ответы [ 3 ]

28 голосов
/ 27 июля 2012

Добавьте

setlocal EnableDelayedExpansion

в начало вашего скрипта, затем используйте !errorlevel! вместо %errorlevel%

Задержка расширения приведет к расширению переменных во время выполненияа не во время разбора

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

Ответ на другой вопрос, который указал мне правильное направление: https://stackoverflow.com/a/6658935/10245

27 голосов
/ 15 октября 2010

IF ERRORLEVEL возвращает TRUE, если код возврата был равен или выше указанного уровня ошибки.В вашем примере, поскольку 0 меньше 1, первый оператор уровня ошибки всегда будет истинным, если фактический код ошибки равен 0 или выше.Сначала вам нужно проверить уровень ошибки 1.

Например:

for %%i in (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 not found
)

Другая проблема заключается в том, хотите ли вы отобразить фактический уровень ошибки из цикла for.Поскольку переменные разрешаются до начала цикла, эхо% errorlevel% будет всегда отображать 0. Если вы хотите отобразить значение во время выполнения, вам нужно изменить фрагмент следующим образом:

setlocal enabledelayedexpansion
for %%i in (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 no process found !errorlevel!
)
0 голосов
/ 15 октября 2010

Вы можете использовать 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 "found:" & WScript.Arguments(i)
        End If 
    Next 
Next

Использование:

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