Управление потоком в командном файле - PullRequest
1 голос
/ 28 апреля 2010

Ссылка Итерация массивов в пакетном файле

У меня есть следующее:

for /f "tokens=1" %%Q in ('query termserver') do (
    if not ERRORLEVEL (
        echo Checking %%Q
        for /f "tokens=1" %%U in ('query user %UserID% /server:%%Q') do (echo %%Q)
    )
)

При запуске query termserver из командной строки первые две строки:

Known
------------------------- 

... сопровождается списком терминальных серверов. Однако я не хочу включать их как часть команды query user. Кроме того, есть около 4 серверов, которые я не хочу включать. Когда я предоставляю UserID с этим кодом, программа быстро завершает работу. Я знаю, что это как-то связано с оператором if. Разве невозможно встроить управление потоком в цикл for?

Я пытался установить переменную точно в соответствии с именами серверов, которые я хотел проверить, но итерация закончилась на первом сервере:

set TermServers=Server1.Server2.Server3.Server7.Server8.Server10

for /f "tokens=2 delims=.=" %%Q in ('set TermServers') do (
    echo Checking %%Q
    for /f "tokens=1" %%U in ('query user %UserID% /server:%%Q') do (echo %%Q)
)

Я бы предпочел этот второй пример первому, если не за чистоту.

Любая помощь по любому из этих вопросов будет принята с благодарностью.

Ответы [ 2 ]

3 голосов
/ 30 апреля 2010

Опять же, здесь нужно отметить несколько вещей.

if errorlevel

Справка для if говорит:

IF [NOT] ERRORLEVEL number command

как синтаксис для условия if errorlevel. То есть вы должны предоставить число для сравнения. Имейте в виду, что if errorlevel n оценивается как true , если код выхода был как минимум n.

So

if errorlevel 1 ...

ловит любую ошибку (которая сигнализируется через код выхода), в то время как

if errorlevel 0 ...

просто всегда верно.

В любом случае, вы, вероятно, хотите

if not errorlevel 1 ...

здесь, так как это условие истинно, если не было ошибок.

Пропуск строк

Команда for /f имеет аргумент skip=n, который можно использовать для пропуска строк в начале. Если ваш вывод начинается с двух строк, которые вам не нужны, тогда вы можете просто сделать

for /f "skip=2 tokens=1" %%Q in ('query termserver') do

Итерация по нескольким известным значениям в for /f

Проблема с вашим вторым фрагментом кода в том, что for повторяет по линиям . Поэтому, когда вы даете ей одну переменную окружения, она будет разбивать ее на токены (и помещать токены в разные переменные), но цикл запускается только один раз на строку . Также обратите внимание, что использование set здесь немного подвержено ошибкам, так как вы можете получить больше, чем хотели бы. Что-то вроде

for /f ... in ("%TermServers%") ...

было бы проще. Тем не менее, это не решает исходную проблему. Самый простой способ решить эту проблему, вероятно, будет выглядеть примерно так:

rem space-separated list of servers
set TermServers=Server1 Server2 Server3 Server7 Server8 Server10

rem call the subroutine with the list of servers
call :query_servers %TermServers%

rem exit the batch file here, to prevent the subroutine from running again afterwards
goto :eof

rem Subroutine to iterate over the list of servers
:query_servers

  rem Process the next server in the list
  rem Note the usage of %1 here instead of a for loop variable
  echo Checking %1          
  for /f "tokens=1" %%U in ('query user %UserID% /server:%1') do (echo %%Q)

  rem Remove the first argument we just processed
  shift

  rem if there is still another server to be processed, then do so
  rem we're mis-using the subroutine label as a jump target here too
  if not [%1]==[] goto query_servers

rem This is kind of a "return" statement for subroutines
goto :eof

(не проверено, но должно работать.)

ETA: Гах, и еще раз мне не хватает самого очевидного ответа:

set TermServers=Server1 Server2 Server3 Server7 Server8 Server10
for %%S in (%TermServers%) do (
    for /f "tokens=1" %%U in ('query user %UserID% /server:%1') do (echo %%Q)
)

Обратите внимание, что это просто for, , а не for /f, и он будет корректно перебирать список значений. Я не знаю, как я это пропустил, извини.

0 голосов
/ 28 апреля 2010

NT shell / пакетный язык недостаточно умен, чтобы принять IF NOT ERRORLEVEL (... - вам нужно сделать явное сравнение, например:

if not %ERRORLEVEL%==0 (
...
...