Итерация массивов в пакетном файле - PullRequest
0 голосов
/ 28 апреля 2010

Я пишу командный файл ( Я задал вопрос по SU ), чтобы выполнить итерацию по терминальным серверам в поисках определенного пользователя. Итак, я получил базовое представление о том, что я пытаюсь сделать.

  1. Введите имя пользователя
  2. Итерация терминальных серверов
  3. Отображение серверов, на которых находится пользователь (их можно время от времени находить на нескольких серверах в зависимости от того, как потеряно соединение)
  4. Отображение меню параметров

Итерация терминальных серверов у меня:

for /f "tokens=1" %%Q in ('query termserver') do (set __TermServers.%%Q)

Теперь я получаю сообщение об ошибке ...

Environment variable __TermServers.SERVER1 not defined

... для каждого из терминальных серверов. Это действительно единственная вещь в моем командном файле на данный момент. Любая идея о том, почему эта ошибка происходит? Очевидно, переменная не определена, но я понял, что команда SET делает именно это.

Я также думаю, что для продолжения работы над итерацией (на каждом терминальном сервере) мне нужно сделать что-то вроде:

:Search    
for /f "tokens=1" %%Q in ('query termserver') do (call Process) 
goto Break

:Process
for /f "tokens=1" %%U in ('query user %%username%% /server:%%Q') do (set __UserConnection = %%C)
goto Search

Однако есть две вещи, которые меня беспокоят по этому поводу:

  1. Значение %% Q все еще живо при вызове Process?
  2. Когда я пойду в Поиск, начнется ли цикл for?

Я делаю это с помощью инструментов, которые есть в моем распоряжении, поэтому сколько бы я ни хотел услышать о PowerShell и других способах сделать это, это было бы бесполезно. У меня есть блокнот и все.

Примечание: я бы продолжил эту строку вопросов о SuperUser, за исключением того, что она, похоже, больше углубляется в специфику программирования.

1 Ответ

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

Хорошо, это довольно много вопросов / проблем / и т.д. в одном: -)

И я до сих пор не совсем понимаю, куда именно вы идете с этим сценарием.

Прежде всего, синтаксис команды set:

set <variable name>=<value>

Если вы просто

set <variable name>

, тогда будут перечислены все переменные окружения, начинающиеся с <variable name>. Если их нет, будет выведено сообщение об ошибке, которое вы видите.

Если вы хотите определить переменную, не заботясь о ее значении, вам все равно нужно предоставить значение. Я обычно использую 1 для таких флагов, так как тогда это больше переключение, чем действительная переменная, содержащая значение:

set Foo=1

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

В вашем случае вы хотите выполнить итерацию по нескольким серверам, а для каждого сервера - по нескольким пользователям. Вы можете сделать это с помощью вложенного цикла:

for /f "tokens=1" %%Q in ('query termserver') do (
   for /f "tokens=1" %%U in ('query user ... /server:%%Q' do (
      ...
   )
)

Что касается ваших двух вопросов там:

  1. Нет, переменная цикла действительна только внутри цикла, но не при вызове подпрограммы. Вы можете передать его подпрограмме, однако:

    for ... in (...) do call Process %%Q
    

    Затем вы можете получить к нему доступ с помощью %1 в подпрограмме. Честно говоря, хотя, в большинстве случаев, я думаю, что вложенные циклы легче читать.

  2. Да.

Еще одна ошибка (одна из которых укусит вас ): Как упоминалось ранее, синтаксис set равен

set variable=value

Обратите внимание, что вокруг знака = есть нет пробела. Если есть, то у вас есть пробел в конце имени переменной или в начале значения:

> set foo = bar
> echo %foo%
%foo%
> echo %foo %
 bar
...