Одним из лучших применений сценариев является внесение массовых изменений в настройки компьютера или пользователя. Менять такие настройки вручную очень утомительно, а, кроме того, есть риск внести ошибку в параметры пользовательской системы. К тому же обычно требуется выполнить изменения за определенное время. В этой статье я представляю сценарий WTSSetUserInfo, который автоматически изменяет настройки службы Windows 2000 Server Terminal Services для пользовательской учетной записи. В следующий раз, когда потребуется изменить путь к серверу или разрешить авторизацию в службе для большой группы пользователей, у вас под рукой будет сценарий, который быстро сделает все необходимые изменения.

 

Сценарий WTSSetUserInfo использует свободно распространяемую утилиту под названием SystemTools Terminal Server Command (TScmd), которая позволяет опрашивать или изменять все 18 настроек службы Terminal Services. Загрузите утилиту TScmd с сайта http://www.systemtools.com/free.htm и скопируйте ее в папку, адрес которой не содержит пробелов (например, D:systoolstscmd.exe). Чтобы отобразить файл подсказки для данной утилиты, нужно открыть окно командной оболочки и ввести команду

 

tscmd.exe /?

 

Вы увидите список из 18 параметров службы Terminal Services, которые можете изменить.

 

Ниже приведен основной синтаксис, используемый для получения информации о службе Terminal Services с помощью команды TScmd:

 

tscmd.exe ServerName UserID Setting

 

где ServerName – имя контроллера домена, на котором размещена информация о пользователе; UserID – имя пользователя, к настройкам которого вы обращаетесь; а Setting – одна из восемнадцати доступных настроек. Например, чтобы получить текущее значение параметра TerminalServerProfilePath, запустите команду

 

tscmd.exe DC35 Asmith TerminalServerProfilePath

 

Базовый синтаксис, используемый для изменения настроек службы Terminal Services

 

tscmd.exe ServerName UserID Setting [NewValue]

где NewValue – новое значение указанного параметра. Например, для изменения настройки TerminalServerProfilePath следует запустить команду

tscmd.exe  DC35 ASmith TerminalServerProfilePath profilesrvrwtsprofilesASmith

Дополнительную информацию о синтаксисе команды TScmd можно найти в файле readme.txt, поставляемом в комплекте с утилитой.

Перед тем как совершить широкомасштабные изменения в настройках групп, а именно для этого мы будем использовать сценарий WTSSetUserInfo, необходимо получить резервную копию текущих настроек. Вряд ли вам понравится, если вы поменяете настройки и обнаружите что необходимо восстановить старые значения, а у вас нет резервных копий. В идеале, у вас должен быть механизм возврата к старым значениям. Сценарий WTSSetUserInfo первым делом сохраняет текущие настройки службы Terminal Services в файле таблицы Microsoft Excel в виде значений, разделенных запятыми (CSV). После изменения значений сценарий снова сохраняет значения в файле таблицы. Имея в наличии сравнительную информацию, мы можем определить, насколько корректно были проведены изменения. Во врезке "Проверка успешного выполнения" перечислены технологии, которые можно использовать для определения корректности проведения операции изменения. При необходимости вы также можете получить информацию, которая требуется для восстановления старых настроек.

Сценарий WTSSetUserInfo Nuts и его логика

В Листинге 1 приведен сценарий WTSSetUserInfo, который состоит из трех похожих процедур: Checkem1, Setem и Checkem2. Эти процедуры вызываются из тела цикла For, который приведен во фрагменте A Листинга 1. Данный цикл For обрабатывает текстовый файл, содержащий имена пользователей.

Сценарий WTSSetUserInfo опрашивает и изменяет четыре параметра службы Terminal Services: AllowLogonTerminalServer, TerminalServerProfilePath, TerminalServerHomeDir и TerminalServerHomeDirDrive. Я выбрал эти четыре параметра, так как именно их администраторы службы Terminal Services используют чаще всего. Можно изменить сценарий таким образом, чтобы с его помощью опрашивать и изменять любой другой параметр, добавив строчку кода в каждую из трех процедур. Применяйте код сценария WTSSetUserInfo в качестве шаблона для создания кода, работающего с другими параметрами.

Первый раз обращение к четырем параметрам осуществляется из процедуры Checkem1 во фрагменте B. Процедура Checkem1 сначала использует команду TScmd, чтобы определить, существует ли указанная учетная запись пользователя. Как видно из тела первого цикла For во фрагменте B, процедура Checkem1 выполняет вызов команды TScmd, после чего передает результаты команде Find. Если команда Find обнаружит строку Error среди выходных данных первого запроса, сценарий пропускает другие опросы и попытки изменить настройки, выводит сообщение об ошибке в файл таблицы и обрабатывает следующую учетную запись пользователя. Если команда Find не обнаружит строку Error (то есть если учетная запись пользователя существует), процедура Checkem1 выполняет еще четыре вызова команды TScmd, чтобы получить текущие значения четырех параметров службы Terminal Services. Процедура сохраняет результаты запросов в четырех переменных: CheckBx1, Ppath1, Hdir1 и Hdrive 1.

После того, как процедура Checkem1 сохраняет исходные значения параметров, цикл For из фрагмента A передает управление процедуре Setem из фрагмента C, который в свою очередь снова вызывает команду TScmd – на этот раз для изменения значений четырех параметров службы Terminal Services. Обратите внимание, что в процедуре Setem команды TScmd аналогичны командам из процедуры Checkem1 за тем лишь исключением, что в конце каждой команды указывается значение.

Как видно из кода во фрагменте C, одни настройки службы Terminal Services требуют указания численных значений, другие – указания переменных. В команде

%TScmdloc% %DC% %user% AllowLogonTerminalServer 1

задание единицы в качестве значения параметра AllowLogonTerminalServer позволяет установить флаг Allow Logon в поле выбора Terminal Server пользовательского интерфейса службы Terminal Services, а значение 0 удаляет флаг в поле выбора. Дополнительную информацию о значениях параметров можно найти в файле readme.txt.

После того, как процедура Setem изменит значения, цикл For из фрагмента A вызовет процедуру Checkem2, которая сохраняет четыре новых значения параметров. Последняя строка кода в процедуре Checkem2 из фрагмента осуществляет вывод значений переменных в файл журнала (то есть в файл таблицы), указанный в начале сценария.

Подготовка к работе и необходимые условия

Я тестировал сценарий WTSSetUserInfo в системах Windows XP Professional Edition Service Pack 1 (SP1) и Windows 2000 Server SP3. Сценарий предполагает, что вы предварительно создали «домашний» профиль и «домашний» каталог, отвечающие обычному принципу именования (то есть их названия построены на основе имени пользователя). Если вы используете другой принцип именования «домашних» профилей и папок пользователей, необходимо изменить сценарий в соответствии с этим принципом. Сценарий WTSSetUserInfo не создает папок – для этого вам придется изменить его.

Чтобы использовать сценарий WTSSetUserInfo, сначала нужно загрузить утилиту TScmd. После загрузки утилиты TScmd следует загрузить файл WTSSetUserInfo.bat. Из-за фиксированной ширины столбцов в печатной версии нам пришлось разорвать некоторые строки кода, поэтому код из печатной версии может работать некорректно.

Для подготовки сценария WTSSetUserInfo к работе необходимо выполнить следующие действия:

1. Укажите местоположение службы в начале файла WTSSetUserInfo.bat. В команде Set TScmdloc=D:systools tscmd.exe

замените значение D:systoolstscmd.exe на путь к утилите в своей системе. Этот путь, а также все пути, используемые в других командах сценария, не должны содержать пробелов.

2. Укажите путь к списку входных данных, который представляет собой текстовый файл, содержащий имена пользователей (одно имя в каждой строке). В команде

Set UserList=D:userlist.txt

замените значение D:userlist.txt на путь к файлу входных данных в вашей системе.

3. Укажите местоположение файла таблице. В команде

Set OutputLog=D:log6-4-04.csv

замените значение «D:log6-4-04.csv» на путь к файлу таблицы.

4. Укажите путь к «домашнему» профилю пользователя (к пути будет добавлена строка \%USERNAME%). В команде

Set ProPath=profilesrvrwtsprofiles

замените значение «profilesrvwtsprofiles» на путь к профилю.

5. Укажите логическое имя диска для «домашней» папки службы Terminal Services. В команде

Set ConnectL=T:

замените значение T: на логическое имя диска.

6. Укажите домашнюю папку (к введенному значению будет добавлена строка \%USERNAME%).В команде

Set HFolder=fileserver2

замените значение « fileserver на имя своей «домашней» папки.

7. Укажите контроллер домена, на котором планируете использовать сценарий WTSSetUserInfo для изменения настроек службы Terminal Services. В команде

Set DC=DC35

замените значение DC35 на имя своего контроллера домена.

Теперь все готово к запуску сценария WTSSetUserInfo. Этот удобный сценарий способен увеличить точность и скорость внесения изменений в настройки учетных записей пользователей Terminal Services в вашем окружении. Позвольте сценарию Let WTSSetUserInfo выполнить утомительную работу за вас!

Листинг 1. WTSSetUserInfo.bat

@ECHO OFF
:: Примечание: Присвоение переменным значений с пробелами может вызвать проблемы
:: Убедитесь, что введенные записи не содержат пробелов.
:: Укажите местоположение службы tscmd.exe с сайта SystemTools.com
:: (путь не должен содержать пробелы).
SET TScmdloc=ServerSysTools scmd.exe
:: Укажите путь к списку входных данных – одно имя пользователя в каждой  строке текстового файла
:: (путь не должен содержать пробелы).
SET UserList=D:userlist.txt
:: Укажите расположение файла журнала (путь не должен содержать пробелы).
SET OutputLog=D:Log6-4-04.csv
:: Укажите путь к профилю (в конец будет добавлена строка %USERNAME%)
:: (путь не должен содержать пробелы).
SET ProPath=profilesrvrwtsprofiles
:: Укажите имя диска.
SET ConnectL=T:
:: Укажите «домашнюю» папку (в конец будет добавлена строка %USERNAME%)
:: (путь не должен содержать пробелы).
SET HFolder=FILESERVER2
:: Укажите контроллер домена, на котором нужно выполнить изменения.
SET DC=DC35
:: Далее не требуется никаких настроек.
ECHO User,TS ProfilePath (old),TS ProfilePath (new),TS HomeDir (old),
 TS HomeDir (new),TS HomeDrive (old),TS HomeDrive (new),
 Check Box (old),Check Box (new)>>"%OutputLog%"
:: BEGIN CALLOUT A
For /F "tokens=1" %%i in (%UserList%) do (set user=%%i) &
 (Call :Checkem1) & (call :Setem) & (Call :Checkem2)
:: END CALLOUT A
ECHO Run completed
GOTO :EOF
:: BEGIN CALLOUT B
:: Эта процедура сохраняет текущие значения.
:Checkem1
SET CheckBx1=N/A
SET Ppath1=N/A
SET Hdir1=N/A
SET Hdrive1=N/A
SET Error=0
For /F "tokens=*" %%i in ('%TScmdloc% %DC% %user%
 AllowLogonTerminalServer ^|Find /I "Error"') Do (SET Error=1) &
(GOTO :EOF)
For /F "tokens=*" %%i in ('%TScmdloc% %DC% %user%
 AllowLogonTerminalServer') Do (set CheckBx1=%%i)
For /F "tokens=*" %%i in ('%TScmdloc% %DC% %user%
 TerminalServerProfilePath^|find ""') Do (set Ppath1=%%i)
For /F "tokens=*" %%i in ('%TScmdloc% %DC% %user%
 TerminalServerHomeDir^|find ""') Do (set Hdir1=%%i)
For /F "tokens=*" %%i in ('%TScmdloc% %DC% %user%
 TerminalServerHomeDirDrive^|find ":"') Do (set Hdrive1=%%i)
GOTO :EOF
:: END CALLOUT B
:: BEGIN CALLOUT C
:: Эта процедура изменяет значения.
:Setem
If "%Error%"=="1" GOTO :EOF
%TScmdloc% %DC% %user% AllowLogonTerminalServer 1
%TScmdloc% %DC% %user% TerminalServerProfilePath
 %ProPath%\%user%
%TScmdloc% %DC% %user% TerminalServerHomeDir
 %HFolder%\%user%
%TScmdloc% %DC% %user% TerminalServerHomeDirDrive
 %ConnectL%
GOTO :EOF
:: END CALLOUT C
:: Эта процедура сохраняет новые значения.
:Checkem2
If "%Error%"=="1" ECHO %user%,USER NOT FOUND,N/A,N/A,N/A,N/A,N/A,N/A,N/A>>"%OutputLog%"
&
 GOTO :EOF
SET CheckBx2=N/A
SET Ppath2=N/A
SET Hdir2=N/A
SET Hdrive2=N/A
For /F "tokens=*" %%i in ('%TScmdloc% %DC% %user%
 AllowLogonTerminalServer') Do (set CheckBx2=%%i)
For /F "tokens=*" %%i in ('%TScmdloc% %DC% %user%
 TerminalServerProfilePath^|find ""') Do (set Ppath2=%%i)
For /F "tokens=*" %%i in ('%TScmdloc% %DC% %user%
 TerminalServerHomeDir^|find ""') Do (set Hdir2=%%i)
For /F "tokens=*" %%i in ('%TScmdloc% %DC% %user%
 TerminalServerHomeDirDrive^|find ":"') Do (set Hdrive2=%%i)
:: BEGIN CALLOUT D
ECHO %user%,%Ppath1%,%Ppath2%,%Hdir1%,%Hdir2%,%Hdrive1%,
 %Hdrive2%,%CheckBx1%,%CheckBx2%>>"%OutputLog%"
:: END CALLOUT D
GOTO :EOF

Проверка успешного выполнения

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

Тест ERRORLEVEL. Большинство служб и утилит используют переменную окружения ERRORLEVEL для сохранения значения (0 или 1), сообщающего об удачном (1) или неудачном (0) исполнении команды. Код из приведенного ниже примера вызывает команду Copy, после чего использует команду If  для того, чтобы проверить значение переменной ERRORLEVEL  и определить, был ли файл успешно скопирован:

Copy C: estfile.txt C: estfile2.txt
If ERRORLEVEL 0
  If not ERRORLEVEL 1
  Echo File copy success
   & Goto :last
Echo File copy failure
:last

Более простой способ проверить корректность выполнения операции на основе опроса переменной ERRORLEVEL предполагает использование двойного символа «and» (&&) или двойного символа «pipe» (||). Операция из следующего примера использует символы &&, чтобы определить, корректно ли выполнена команда Copy:

Copy C: estfile.txt C: estfile2.txt && Echo File copy success & Goto :last
Echo File copy failure
:last

Чтобы обнаружить ошибку при исполнении команды Copy, используйте символы ||:

Copy C: estfile.txt C: estfile2.txt || Echo File copy failed & Goto :last
Echo File copy success
:last

Недостаток теста ERRORLEVEL заключается в том, что он не работает с некоторыми командами. Например, обратите внимание на следующий код:

Ping Server1 && Echo Server1 ping success & Goto :last
Echo Server1 ping failure
:last

Если Server1 – неверное имя сервера, команда вернет обоснованное сообщение об ошибке. Однако если Server1 – корректное имя сервера, но сервер Server1 отключен, команда Ping вернет ложное сообщение об успешном завершении операции, то есть команда Ping якобы «выполняется успешно», хотя узел был отключен.

Тест поиска строки. Второй способ проверить корректность выполнения команды – внедрить команду в тело цикла For, перехватить выходные данные внедренной команды (например, команды Ping) и использовать команду Find для поиска выходных данных, наличие которых будет основанием для выдачи сообщения об успешном выполнении. В следующем примере осуществляется поиск строки Reply, которая является результатом успешно выполненной команды Ping:

For /F "tokens=1" %%i in ('Ping -n 1 Server1^ | Find "Reply"') Do Echo Server1 is on & Goto :last
Echo Server1 is off
:last

Тест выполнения запросов. Третий способ протестировать корректность выполнения команды - запуск команды (в данном случае, запуск команды TScmd для изменения настроек службы Terminal), после чего сразу же проверяется установленное значение. Сценарий WTSSetUserInfo использует метод проверки выполнения запросов по трем причинам. Во-первых, служба TScmd не может корректно работать с методом проверки переменной ERRORLEVEL. Во-вторых, хотя тест проверки строки работает со службой TScmd, она не возвращает точных значений настроек, используемых сценарием WTSSetUserInfo.bat. Помните, что по окончании операции изменения необходимо сохранить в таблице как новые, так и старые настройки. В-третьих, метод проверки выполнения запросов соответствует подходу, когда производится перехват значений до того, как сценарий изменит их, и после изменения. Технология «до и после» предполагает размещение всех данных в одной таблице для того, чтобы вы могли убедиться, что настройки верны, и распознать проблемы, например, неверное указание пути сервера.