. Глобальные группы могут быть членами локальных групп, но не наоборот. При включении глобальных групп в локальные, глобальные группы будут полностью наследовать соответствующие права, установленные для этих локальных групп.

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

Результатом этой работы стал сценарий NewLocalGroup.vbs, содержащий исчерпывающие комментарии. Данный сценарий может запускаться на любых системах семейства NT (от NT 4.0 до Windows 2003), на которых установлены компоненты Active Directory Service Interfaces (ADSI), Windows Script Host (WSH) 5.6 и Windows Management Instrumentation (WMI). Аналогичные требования должны соблюдаться и для удаленных компьютеров.

Сценарий NewLocalGroup.vbs выполняет следующие действия:

  • подключение к удаленному компьютеру
  • вывод списка локальных групп для проверки существования группы с тем же именем
  • создание локальной группы
  • включение глобальной группы в новую локальную группу
  • вывод отчета с результатами работы.

Однако для того, чтобы сценарий мог выполнять все эти задачи, ему необходимы некоторые дополнительные данные.

Получение нужных данных

При запуске NewLocalGroup.vbs используется аргумент командной строки, через который в сценарий передается имя компьютера, к которому нужно подключаться. Однако имена соответствующих локальных и глобальных групп жестко запрограммированы в тексте сценария. Данный подход был выбран из тех соображений, что при каждом запуске сценария мы, скорее всего, будем подключаться к различным компьютерам, однако едва ли будем столь часто изменять имена локальных или глобальных групп.

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

NewLocalGroup.vbs [argument]

где argument может представлять собой один из перечисленных ниже вариантов:

  • имя компьютера (одно или несколько)
  • слово all (при этом сценарий будет запущен для всех серверов, имеющихся в дереве AD)
  • слово file (если нужно передать сценарию входной файл, содержащий список имен компьютеров)

Если требуется запустить сценарий на локальной машине, никаких аргументов указывать не нужно.

В сценарии NewLocalGroup.vbs имена создаваемой локальной группы и глобальной группы, которая будет в нее включаться, хранятся в переменных sLGroup и sGGroup, соответственно. В результате при необходимости изменения имен групп это можно будет делать только в одном месте текста сценария. При адаптации сценария для его использования в конкретной сети этим переменным необходимо присвоить актуальные значения. Аналогичным образом следует изменить значение переменной sDC, которая определяет имя вашего контроллера домена (DC) (см. Листинг 1).

Если вы предполагаете использовать входной файл для передачи имен компьютеров в сценарий или хотите запустить его на всех компьютерах имеющихся в AD, тогда необходимо внести в текст NewLocalGroup.vbs другие изменения, которые будут обсуждаться в следующем разделе.

Подключение к удаленным компьютерам

Как обычно, в начале сценария NewLocalGroup.vbs объявляются необходимые переменные, а затем производится проверка, использовался ли аргумент при запуске сценария. Если аргумент есть, тогда он записывается в переменную sInput, после чего с помощью оператора Select Case выполняется анализ его значения. Как видно из Листинга 2, оператор Select Case проверяет три значения аргумента: file, all и /?. Если аргумент не соответствует ни одному из перечисленных значений, тогда отрабатывается ветвь Case Else.

Case "file". В этом случае оператор Select Case проверяет, имеет ли аргумент значение "file". Если да, тогда сценарий открывает заданный входной файл и считывает его содержимое (т.е. имена компьютеров) в переменную sComputerName. После закрытия файла запускается цикл For Each….Next, который последовательно перебирает имена компьютеров в переменной sComputerName и запускает для каждого имени процедуру EnumGroups.

Когда вы используете входной файл для передачи имен компьютеров, необходимо предварительно создать соответствующий текстовый файл, в котором будут содержаться имена тех компьютеров, к которым вы планируете подключаться. Так как в сценарии в качестве символа-разделителя используется возврат каретки (vbCrLf), в этом файле каждое имя должно находиться на отдельной строке. При этом также потребуется изменить в сценарии значение C:ScriptsServers.txt (см. фрагмент с меткой A Листинга 2) на актуальный путь к входному файлу.

Case "all". Здесь Select Case проверяет, имеет ли аргумент значение "all". Если это так, сценарий обращается к соответствующей службе LDAP (Lightweight Directory Access Protocol), извлекает имена всех компьютеров AD и сохраняет их в виде коллекции colComputers. Далее выполняется последовательный перебор элементов коллекции и запуск процедуры EnumGroups для каждого имени компьютера.

Если вы используете аргумент all, тогда необходимо отредактировать фрагмент кода с меткой B (см. Листинг 2), указав соответствующий путь.

Case "/?". В данном случае проверяется, имеет ли аргумент значение "/?" (Справка - Help). Если да, тогда выводятся инструкции по правильному запуску сценария NewLocalGroup.vbs.

Case Else. Этот случай соответствует ситуации, когда аргумент не равен ни одному из перечисленных выше значений (т.е. в качестве аргумента было задано одно или более имен компьютеров). В данном случае заданные имена последовательно перебираются, и для каждого из них запускается процедура EnumGroups.

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

Получение информации о существующих локальных группах

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

С формальной точки зрения, данная процедура не является необходимой, поскольку при попытке создания на компьютере группы с именем, идентичным существующему, сценарий прервет свое выполнение, и вы получите соответствующее сообщение об ошибке. Однако ради завершенности, а также для того, чтобы исключить возможность непреднамеренного добавления некорректного имени группы, данная процедура была включена в NewLocalGroup.vbs.

Извлечение информации о группах может потребовать времени, поэтому если вам кажется, что сценарий выполняется слишком долго, данную процедуру можно из сценария исключить. Необходимые для этого действия очень просты. В конструкции Select Case (см. Листинг 2) нужно изменить все встречающиеся там слова EnumGroups на слово NewLocal. В результате вместо процедуры EnumGroups сценарий будет вызывать процедуру NewLocal.

Создание локальной группы

После того как выяснилось, что локальной группы с указанным именем на компьютере нет, сценарий вызывает процедуру создания группы – NewLocal. Как показано в Листинге 3, эта процедура устанавливает соединение со службой WMI данного компьютера, создает объект, соответствующий этому компьютеру, и создает локальную группу с заданным именем. После того как NewLocal занесет соответствующие изменения в AD, она генерирует сообщение об успешном создании новой локальной группы. Завершается процедура NewLocal вызовом процедуры AddGlobal.

Добавление глобальной группы

Процедура AddGlobal предназначена для включения существующей глобальной группы (имя которой было задано в начале сценария) в созданную локальную группу. Как видно из Листинга 4, сначала данная процедура создает два объекта: объект, соответствующий локальной группе на заданном компьютере, и объект, соответствующий глобальной группе, находящейся на DC. Данным объектам назначаются две объектные переменные – oLGroup и oGGroup, соответственно. В рассматриваемом сценарии для задания имени глобальной группы используется глобальная переменная, однако вместо этого можно задействовать локальную переменную, сделав, таким образом, эту процедуру более переносимой. Далее процедура AddGlobal включает глобальную группу в состав локальной и формирует соответствующий отчет о результатах работы.

Быстрая альтернатива

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


Листинг 1. Параметры, подлежащие изменению при адаптации сценария
sLGroup = "NewGroup"
sGGroup = "Domain Users"
sDC = "MyDomainController"

Листинг 2. Оператор Select Case
Select Case sInput
Case "file"
' BEGIN CALLOUT A
Const INPUT_FILE_NAME = "C:ScriptsServers.txt"
' END CALLOUT A
Const FOR_READING = 1
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFile = oFSO.OpenTextFile(INPUT_FILE_NAME, _
FOR_READING)
sComputerName = oFile.ReadAll
oFile.Close
aComputers = Split(sComputerName, vbCrLf)
For Each sComputerName in aComputers
Call EnumGroups
Next
WScript.Quit
Case "all"
WScript.Echo "Будут опрошены все компьютеры, на которых запущена служба WMI."
' BEGIN CALLOUT B
Set colComputers = _
_GetObject(LDAP://CN=Computers, DC=labrynth, DC=com)
' END CALLOUT B
For Each oComputer in colComputers
sComputerName = oComputer.CN
Call EnumGroups
Next
Case "/?"
WScript.Echo "Инструкции:"
WScript.Echo "Данный сценарий создает локальную группу", sLGroup,
WScript.Echo "на выбранном компьютере (компьютерах),"
WScript.Echo " если на них запущена служба WMI."
WScript.Echo "Для создания групп на всех серверах Active Directory, используйте аргумент 'all'."
WScript.Echo "Для создания групп на нескольких компьютерах,"
WScript.Echo "укажите их имена в качестве аргументов сценария."
WScript.Echo "Чтобы считать имена компьютеров из файла используйте аргумент 'file'."
WScript.Echo "Для создания группы на локальном компьютере,"
WScript.Echo "запускайте данный сценарий БЕЗ АРГУМЕНТОВ."
Case Else
For Each sArgument in WScript.Arguments
sComputerName = sArgument
Call EnumGroups
Next
End Select

Листинг 3. Процедура NewLocal
Sub NewLocal
Set oWMIService  = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!" & _
sComputerName & "
ootcimv2")
Set oComputer = _
GetObject("WinNT://" & sComputerName & ",computer")
Set oLGroup = oComputer.Create("group", sLGroup)
oLGroup.SetInfo
WScript.Echo sLGroup, "has been created on", sComputerName
Call AddGlobal
End Sub

Листинг 4. Процедура AddGlobal
Sub AddGlobal
Set oLGroup = GetObject("WinNT://" & sComputerName & _
"/" & sLGroup & ",group")
Set oGGroup = GetObject("WinNT://" & sDC & "/" & _
sGGroup & ",group")
oLGroup.Add(oGGroup.ADsPath)
WScript.Echo oGGroup.Name, "is now in", oLGroup.Name
End Sub