Командная строка и сценарии Windows
Попов Андрей Владимирович

Содержание


Лекция 1. Эволюция инструментов для автоматизации работы в Microsoft Windows

Описываются стандартные (входящие в поставку операционной системы) программные средства для автоматизации администрирования и повседневной работы в Microsoft Windows. Обсуждаются возможности командного интерпретатора Cmd.exe, сервера сценариев WSH и оболочки Windows PowerShell

Эволюция инструментов для автоматизации работы в Microsoft Windows

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

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

Однако подобная модель управления не является масштабируемой: если администрировать не один, а десять серверов, используя стандартные графические инструменты, то одну и ту же последовательность изменения элементов управления в диалоговых окнах придется повторить десять раз, следовательно, в этом случае остро встает вопрос об автоматизации выполнения рутинных операций (например, проведение инвентаризации оборудования и программного обеспечения, мониторинг работы служб, анализ журналов событий и т.д.) на множестве компьютеров. Помочь в этом могут либо специальные (как правило тяжеловесные и недешевые) приложения типа Microsoft Systems Management Server (SMS), либо сценарии, которые пишутся администраторами самостоятельно (на языке оболочки командной строки или на специальных языках сценариев) и поддерживаются непосредственно операционной системой, без установки сторонних программных продуктов.

Поэтому для профессионала, занимающегося администрированием информационных систем на базе Windows, знание возможностей командной строки, сценариев и технологий автоматизации, поддерживаемых данной операционной системой, просто необходимо.

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

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

В Unix-системах в качестве инструмента автоматизации выступает стандартная оболочка (shell) или ее модификации (bashell, kshell, cshell и т.д.), причем этот аспект операционной системы стандартизирован в рамках POSIX (стандарт мобильных систем).

В операционной системе Windows дело обстоит сложнее. На сегодняшний день одного "идеального" средства автоматизации, удовлетворяющего сразу всем перечисленным выше требованиям, в Windows нет; в последних версиях операционной системы поддерживаются несколько стандартных инструментов автоматизации, сильно отличающихся друг от друга: оболочка командной строки cmd.exe, среда выполнения сценариев Windows Script Host и оболочка Microsoft PowerShell. Поэтому администратору или пользователю Windows приходится выбирать, каким именно подходом воспользоваться для решения определенной задачи, а для этого желательно иметь четкое представление о сильных и слабых сторонах данных средств автоматизации. Здесь мы кратко обсудим достоинства и недостатки каждого из них (теоретические и практические подробности будут рассмотрены в последующих лекциях).

Оболочка командной строки command.com/cmd.exe

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

Замечание

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

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

Начиная с версии Windows NT, оболочка командной строки представляется интерпретатором Cmd.exe, который расширяет возможности оболочки command.com операционной системы MS-DOS. В свою очередь функциональность командного интерпретатора command.com была позаимствована из операционной системы CP/M, оболочка которой представляла собой значительно упрощенный и урезанный вариант оболочки Unix-систем.

Таким образом, оболочка командной строки MS-DOS изначально уступала Unix-оболочкам по удобству работы и развитости языка сценариев; в командной оболочке Windows (cmd.exe), несмотря на все сделанные улучшения, не удалось преодолеть данное отставание ни в режиме интерактивной работы (например, в cmd.exe отсутствует поддержка псевдонимов для длинных названий команд и не реализовано автоматическое завершение команд при вводе их с клавиатуры), ни в синтаксисе или возможностях языка командных файлов. Ситуация усугублялась тем, что Windows всегда проигрывала Unix-системам в количестве и функциональных возможностях стандартных (не требующих дополнительной установки) утилит командной строки, а также в качестве и полноте встроенной справочной системы по командам оболочки.

На практике проблему отсутствия нужной функциональности у стандартных команд приходится решать либо с помощью утилит пакета Windows Resource Kit для соответствующей версии операционной системы, либо путем поиска подходящей утилиты сторонних производителей. Кроме того, в Windows можно пользоваться POSIX-совместимыми утилитами и оболочками с помощью пакета Microsoft Services For Unix (SFU). Данный продукт разрабатывался еще для Windows NT и первоначально не входил в состав операционной системы, его нужно было приобретать за отдельную плату. В дальнейшем пакет SFU стал бесплатным и даже был включен в состав операционной системы Windows Server 2003 R2.

Итак, учитывая все сказанное выше, мы можем сделать следующий вывод: оболочка командной строки cmd.exe и командные файлы – наиболее универсальные и простые в изучении средства автоматизации работы в Windows, доступные во всех версиях операционной системы, которые, однако, существенно проигрывают аналогичным инструментам в Unix-системах и не обеспечивают доступ к объектным моделям, поддерживаемым операционной системой (COM, WMI, .NET).

Поддержка языков сценариев. Сервер сценариев Windows Script Host

Следующим шагом в развитии средств и технологий автоматизации в операционной системе Windows стало появление сервера сценариев Windows Script Host (WSH). Этот инструмент разработан для всех версий Windows и позволяет непосредственно в операционной системе выполнять сценарии на полноценных языках сценариев (по умолчанию, VBScript и JScript), которые до этого были доступны только внутри HTML-страниц и работали в контексте безопасности веб-браузера (в силу этого подобные сценарии, например, могли не иметь доступа к файловой системе локального компьютера).

По сравнению с командными файлами интерпретатора cmd.exe сценарии WSH имеют несколько преимуществ.

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

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

В-третьих, из сценариев WSH можно обращаться к службам любых приложений-серверов автоматизации (например, программ из пакета Microsoft Office), которые регистрируют в операционной системе свои объекты.

Наконец, сценарии WSH позволяют работать с объектами информационной модели Windows Management Instrumentation (WMI), обеспечивающей программный интерфейс управления всеми компонентами операционной модели, а также с объектами службы каталогов Active Directory Service Interface (ADSI) (объектные модели WMI и ADSI будут обсуждаться подробнее в следующих лекциях).

Следует также отметить, что технология WSH поддерживается в Windows уже довольно давно, в Интернете (в том числе на сайте Microsoft) можно найти множество готовых сценариев, выполняющих ту или иную операцию и при определенных навыках и знаниях быстро "подогнать" эти сценарии под свои конкретные задачи.

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

Большим минусом является то, что в операционной системе по умолчанию нет полноценной подробной справочной информации по объектам WSH и языкам VBScript/JScript (документацию приходится искать в Интернете на сайте Microsoft). Другими словами, если вы, например, не помните синтаксис определенной команды VBScript/JScript или точное название свойства объекта WSH, под рукой у вас нет распечатанной документации, а компьютер не имеет выхода в Интернет, то написать корректный сценарий вам просто не удастся (в данном аспекте командные файлы более универсальны, так как практически у всех команд есть по крайней мере встроенное описание используемых ими ключей, а в операционной системе имеется справочный файл с информацией о всех стандартных командах).

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

Таким образом, можно дать следующую общую оценку: сценарии WSH – это универсальный инструмент, который в любой версии операционной системы Windows позволяет решать задачи автоматизации практически любой степени сложности, но требует при этом большой работы по изучению самих языков сценариев и ряда смежных технологий управления операционной системой (WMI, ADSI и т.п.).

Командная оболочка Microsoft PowerShell

Итак, к началу XXI века ситуацию со средствами автоматизации работы в Windows нельзя было назвать совсем хорошей. С одной стороны функциональности и гибкости языка оболочки cmd.exe было явно недостаточно, а с другой стороны сценарии WSH, работающие с объектными моделями ADSI и WMI, оказались слишком сложными для пользователей среднего уровня и начинающих администраторов.

В 2000 году была начата разработка новой оболочки для доступа к объектам WMI из командной строки (WMI Command-line, WMIC). Этот продукт оказался не особенно удачным, так как в нем акцент был сделан на функциональные особенности WMI, а не на удобство работы пользователя. Начав дорабатывать WMIC, специалисты Microsoft поняли, что можно реализовать оболочку, которая не ограничивалась бы только работой с объектами WMI, а также предоставляла бы доступ к любым классам платформы .NET Framework, обеспечивая тем самым возможность пользоваться из командной строки всеми мощными функциональными возможностями данной среды.

Перед разработчиками новой оболочки, получившей название Windows PowerShell (предварительное название – Monad), стояли следующие основные цели и задачи, которые были успешно решены:

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

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

Отметим, что PowerShell одновременно является и оболочкой командной строки (пользователь работает в интерактивном режиме) и средой выполнения сценариев, которые пишутся на специальном языке PowerShell.

Интерактивный сеанс в PowerShell похож на работу в оболочке Unix-систем: все команды в PowerShell имеют подробную встроенную справку (для большинства команд приводятся примеры их использования), поддерживается функция автоматического завершения названий команд и их параметров при вводе с клавиатуры, для многих команд имеются псевдонимы, аналогичные названиям Unix-утилит (ls, pwd, tee и т.д.).

Язык PowerShell несложен для изучения, писать на нем сценарии, обращающиеся к внешним объектам, проще, чем на VBScript или JScript. Отдельное внимание было уделено вопросам безопасности при работе со сценариями (например, запустить сценарий можно только с указанием полного пути к нему, а по умолчанию запуск сценариев PowerShell в системе вообще запрещен).

В целом, оболочка PowerShell намного удобнее и мощнее своих предшественников (cmd.exe и WSH), а основным недостатком, сдерживающим распространение нового инструмента, является тот факт, что PowerShell работает не во всех версиях операционной системы Windows. Оболочкой можно пользоваться только на версиях не ниже Windows XP Service Pack 2 с установленным пакетом .NET Framework 2.0.

Лекция 2. Оболочка командной строки Windows. Интерпретатор Cmd.exe

Рассматриваются внутренние команды, поддерживаемые интерпретатором Cmd.exe, и наиболее часто используемые внешние команды (утилиты командной строки). Описываются механизмы перенаправления ввода/вывода, конвейеризации и условного выполнения команд. Даются примеры команд для работы с файловой системой

Оболочка командной строки Windows. Интерпретатор Cmd.exe

В операционной системе Windows, как и в других операционных системах, интерактивные (набираемые с клавиатуры и сразу же выполняемые) команды выполняются с помощью так называемого командного интерпретатора, иначе называемого командным процессором или оболочкой командной строки (command shell). Командный интерпретатор или оболочка командной строки — это программа, которая, находясь в оперативной памяти, считывает набираемые вами команды и обрабатывает их. В Windows 9x, как и в MS-DOS, командный интерпретатор по умолчанию был представлен исполняемым файлом command.com. Начиная с версии Windows NT, в операционной системе реализован интерпретатор команд Cmd.exe, обладающий гораздо более мощными возможностями.

Запуск оболочки

В Windows NT/2000/XP файл Cmd.exe, как и другие исполняемые файлы, соответствующие внешним командам операционной системы, находятся в каталоге %SystemRoot%\SYSTEM32 (значением переменной среды %SystemRoot% является системный каталог Windows, обычно C:\Windows или C:\WinNT). Для запуска командного интерпретатора (открытия нового сеанса командной строки) можно выбрать пункт Выполнить… (Run) в меню Пуск (Start), ввести имя файла Cmd.exe и нажать кнопку OK. В результате откроется новое окно (см. рис. 2.1), в котором можно запускать команды и видеть результат их работы.

Командное окно интерпретатора Cmd.exe в Windows XP


Рис. 2.1.  Командное окно интерпретатора Cmd.exe в Windows XP

Внутренние и внешние команды. Структура команд

Некоторые команды распознаются и выполняются непосредственно самим командным интерпретатором — такие команды называются внутренними (например, COPY или DIR ) Другие команды операционной системы представляют собой отдельные программы, расположенные по умолчанию в том же каталоге, что и Cmd.exe, которые Windows загружает и выполняет аналогично другим программам. Такие команды называются внешними (например, MORE или XCOPY ).

Рассмотрим структуру самой командной строки и принцип работы с ней. Для того, чтобы выполнить команду, вы после приглашения командной строки (например, C:\> ) вводите имя этой команды (регистр не важен), ее параметры и ключи (если они необходимы) и нажимаете клавишу <Enter>. Например:

C:\>COPY C:\myfile.txt A:\ /V

Имя команды здесь — COPY, параметры — C:\myfile.txt и A:\, а ключом является /V. Отметим, что в некоторых командах ключи могут начинаться не с символа /, а с символа – (минус), например, -V.

Многие команды Windows имеют большое количество дополнительных параметров и ключей, запомнить которые зачастую бывает трудно. Большинство команд снабжено встроенной справкой, в которой кратко описываются назначение и синтаксис данной команды. Получить доступ к такой справке можно путем ввода команды с ключом /?. Например, если выполнить команду ATTRIB /?, то в окне MS-DOS мы увидим следующий текст:

Отображение и изменение атрибутов файлов.
ATTRIB [+R|-R] [+A|-A] [+S|-S] [+H|-H] [[диск:][путь]имя_файла] [/S]
  +   Установка атрибута.
  -   Снятие атрибута.
  R   Атрибут "Только чтение".
  A   Атрибут "Архивный".
  S   Атрибут "Системный".
  H   Атрибут "Скрытый".
  /S  Обработка файлов во всех вложенных папках указанного пути.

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

XCOPY /? | MORE

В этом случае после заполнения очередного экрана вывод помощи будет прерываться до нажатия любой клавиши. Кроме того, используя символы перенаправления вывода > и >>, можно текст, выводимый на экран, направить в текстовый файл для дальнейшего просмотра. Например, для вывода текста справки к команде XCOPY в текстовый файл xcopy.txt, используется следующая команда:

XCOPY /? > XCOPY.TXT

Замечание

Вместо имени файла можно указывать обозначения устройств компьютера. В Windows поддерживаются следующие имена устройств: PRN (принтер), LPT1–LPT3 (соответствующие параллельные порты), AUX (устройство, присоединяемое к последовательному порту 1), COM1–COM3 (соответствующие последовательные порты), CON (терминал: при вводе это клавиатура, при выводе - монитор), NUL (пустое устройство, все операции ввода/вывода для него игнорируются).

Перенаправление ввода/вывода и конвейеризация (композиция) команд

Рассмотрим более подробно поддерживаемые в Windows UNIX-подобные концепции переназначения устройств стандартного ввода/вывода и конвейерного выполнения команд.

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

Из командной строки эти возможности реализуются следующим образом. Для того, чтобы перенаправить текстовые сообщения, выводимые какой-либо командой, в текстовый файл, нужно использовать конструкцию

команда > имя_файла

Если при этом заданный для вывода файл уже существовал, то он перезаписывается (старое содержимое теряется), если не существовал — создается. Можно также не создавать файл заново, а дописывать информацию, выводимую командой, в конец существующего файла. Для этого команда перенаправления вывода должна быть задана так:

команда >> имя_файла

С помощью символа < можно прочитать входные данные для заданной команды не с клавиатуры, а из определенного (заранее подготовленного) файла:

команда < имя_файла

Приведем несколько примеров перенаправления ввода/вывода.

  1. Вывод встроенной справки для команды COPY в файл copy.txt:
    COPY /? > copy.txt
  2. Добавление текста справки для команды XCOPY в файл copy.txt:
    XCOPY /? >> copy.txt
  3. Ввод новой даты из файла date.txt (DATE — это команда для просмотра и изменения системной даты):
    DATE < date.txt

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

команда 2> имя_файла

В этом случае стандартный вывод будет производиться в файл. Также имеется возможность информационные сообщения и сообщения об ошибках выводить в один и тот же файл. Делается это следующим образом:

команда > имя_файла 2>&1

Например, в приведенной ниже команде стандартный выходной поток и стандартный поток ошибок перенаправляются в файл copy.txt:

XCOPY A:\1.txt C: > copy.txt 2>&1

Наконец, с помощью конструкции

команда1 | команда2

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

Используя механизмы перенаправления ввода/вывода и конвейеризации, можно из командной строки посылать информацию на различные устройства и автоматизировать ответы на запросы, выдаваемые командами или программами, использующими стандартный ввод. Для решения таких задач подходит команда

ECHO [сообщение]

которая выводит сообщение на экран. Рассмотрим примеры использования этой команды.

  1. Посылка символа прогона на принтер:
    ECHO ^L > PRN
  2. Удаление всех файлов в текущем каталоге без предупреждения (автоматический положительный ответ на запрос об удалении):
    ECHO y | DEL *.*
  3. Соединение по телефону из командной строки (модем связан с портом COM2):
    ECHO ATDT 1(123)555-1234 > COM2
Команды MORE и SORT

Одной из наиболее часто использующихся команд, для работы с которой применяется перенаправление ввода/вывода и конвейеризация, является MORE. Эта команда считывает стандартный ввод из конвейера или перенаправленного файла и выводит информацию частями, размер каждой из которых не больше размера экрана. Используется MORE обычно для просмотра длинных файлов. Возможны три варианта синтаксиса этой команды:

MORE [диск:][путь]имя_файла
MORE < [диск:][путь]имя_файла
имя_команды | MORE

Параметр [диск:][путь]имя_файла определяет расположение и имя файла с просматриваемыми на экране данными. Параметр имя_команды задает команду, вывод которой отображается на экране (например, DIR или команда TYPE, использующаяся для вывода содержимого текстового файла на экран). Приведем два примера.

Для поэкранного просмотра помощи команды DIR используется команда:

DIR /? | MORE

Для поэкранного просмотра текстового файла news.txt возможны следующие варианты команд:

MORE news.txt
MORE < news.txt
TYPE news.txt | MORE

Другой распространенной командой, использующей перенаправление ввода/вывода и конвейеризацию, является SORT. Эта команда работает как фильтр: она считывает символы в заданном столбце, упорядочивает их в возрастающем или убывающем порядке и выводит отсортированную информацию в файл, на экран или другое устройство. Возможны два варианта синтаксиса этой команды:

SORT [/R] [/+n] [[диск1:][путь1]файл1] [> [диск2:][путь2]файл2]

или

[команда ] | SORT [/R] [/+n] [> [диск2:][путь2]файл2]

В первом случае параметр [диск1:][путь1]файл1 определяет имя файла, который нужно отсортировать. Во втором случае будут отсортированы выходные данные указанной команды. Если параметры файл1 или команда не заданы, то SORT будет считывать данные с устройства стандартного ввода.

Параметр [диск2:][путь2]файл2 задает файл, в который будет направляться сортированный вывод; если этот параметр не задан, то вывод будет направлен на устройство стандартного вывода.

По умолчанию сортировка выполняется в порядке возрастания. Ключ /R позволяет изменить порядок сортировки на обратный (от Z к A и затем от 9 до 0). Например, для поэкранного просмотра отсортированного в обратном порядке файла price.txt, нужно задать следующую команду:

SORT /R < price.txt |MORE

Ключ /+n задает сортировку в файле по символам n-го столбца. Например, /+10 означает, что сортировка должна осуществляться, начиная с 10-й позиции в каждой строке. По умолчанию файл сортируется по первому столбцу.

Условное выполнение и группировка команд

В командной строке Windows NT/2000/XP можно использовать специальные символы, которые позволяют вводить несколько команд одновременно и управлять работой команд в зависимости от результатов их выполнения. С помощью таких символов условной обработки можно содержание небольшого пакетного файла записать в одной строке и выполнить полученную составную команду.

Используя символ амперсанда &, можно разделить несколько утилит в одной командной строке, при этом они будут выполняться друг за другом. Например, если набрать команду DIR & PAUSE & COPY /? и нажать клавишу <Enter>, то вначале на экран будет выведено содержимое текущего каталога, а после нажатия любой клавиши — встроенная справка команды COPY.

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

ECHO Абв & COPY /?

и нажать клавишу <Enter>, то произойдет выполнение подряд двух команд: ECHO Абв и COPY /? (команда ECHO выводит на экран символы, указанные в командной строке после нее). Если же выполнить команду

ECHO Абв ^& COPY /?

то на экран будет выведено

Абв & COPY /?

В этом случае просто выполняется одна команда ECHO с соответствующими параметрами.

Условная обработка команд в Windows осуществляется с помощью символов && и || следующим образом. Двойной амперсанд && запускает команду, стоящую за ним в командной строке, только в том случае, если команда, стоящая перед амперсандами была выполнена успешно. Например, если в корневом каталоге диска C: есть файл plan.txt, то выполнение строки TYPE C:\plan.txt && DIR приведет к выводу на экран этого файла и содержимого текущего каталога. Если же файл C:\plan.txt не существует, то команда DIR выполняться не будет.

Два символа || осуществляют в командной строке обратное действие, т.е. запускают команду, стоящую за этими символами, только в том случае, если команда, идущая перед ними, не была успешно выполнена. Таким образом, если в предыдущем примере файл C:\plan.txt будет отсутствовать, то в результате выполнения строки TYPE C:\plan.txt || DIR на экран выведется содержимое текущего каталога.

Отметим, что условная обработка действует только на ближайшую команду, то есть в строке

TYPE C:\plan.txt && DIR & COPY /?

команда COPY /? запустится в любом случае, независимо от результата выполнения команды TYPE C:\plan.txt.

Несколько утилит можно сгруппировать в командной строке с помощью скобок. Рассмотрим, например, две строки:

TYPE C:\plan.txt && DIR & COPY /?
TYPE C:\plan.txt && (DIR & COPY /?)

В первой из них символ условной обработки && действует только на команду DIR, во второй — одновременно на две команды: DIR и COPY.

Примеры команд для работы с файловой системой

Рассмотрим некоторые наиболее часто используемые команды для работы с файловой системой. Отметим сначала несколько особенностей определения путей к файлам в Windows.

Пути к объектам файловой системы

Напомним, что файловая система логически имеет древовидную структуру и имена файлов задаются в формате [диск:][путь\]имя_файла, то есть обязательным параметром является только имя файла. При этом, если путь начинается с символа "\", то маршрут вычисляется от корневого каталога, иначе — от текущего каталога. Например, имя C:123.txt задает файл 123.txt в текущем каталоге на диске C:, имя C:\123.txt — файл 123.txt в корневом каталоге на диске C:, имя ABC\123.txt — файл 123.txt в подкаталоге ABC текущего каталога.

Существуют особые обозначения для текущего каталога и родительского каталогов. Текущий каталог обозначается символом . (точка), его родительский каталог — символами .. (две точки). Например, если текущим каталогом является C:\WINDOWS, то путь к файлу autoexec.bat в корневом каталоге диска C: может быть записан в виде ..\autoexec.bat.

В именах файлов (но не дисков или каталогов) можно применять так называемые групповые символы или шаблоны: ? (вопросительный знак) и * (звездочка). Символ * в имени файла означает произвольное количество любых допустимых символов, символ ? — один произвольный символ или его отсутствие. Скажем, под шаблон text??1.txt подходят, например, имена text121.txt и text911.txt, под шаблон text*.txt — имена text.txt, textab12.txt, а под шаблон text.* — все файлы с именем text и произвольным расширением.

Для того, чтобы использовать длинные имена файлов при работе с командной строкой, их нужно заключать в двойные кавычки. Например, чтобы запустить файл с именем 'Мое приложение.exe' из каталога 'Мои документы', нужно в командной строке набрать "C:\Мои документы\Мое приложение.exe" и нажать клавишу <Enter>.

Перейдем теперь непосредственно к командам для работы с файловой системой.

Команда CD

Текущий каталог можно изменить с помощью команды

CD [диск:][путь\]

Путь к требуемому каталогу указывается с учетом приведенных выше замечаний. Например, команда CD \ выполняет переход в корневой каталог текущего диска. Если запустить команду CD без параметров, то на экран будут выведены имена текущего диска и каталога.

Команда COPY

Одной из наиболее часто повторяющихся задач при работе на компьютере является копирование и перемещение файлов из одного места в другое. Для копирования одного или нескольких файлов используется команда COPY.

Синтаксис этой команды:

COPY [/A|/B] источник [/A|/B]  [+ источник [/A|/B] [+ ...]] 
  [результат [/A|/B]] [/V][/Y|/–Y]

Краткое описание параметров и ключей команды COPY приведено в табл. 2.1.

Таблица 2.1. Параметры и ключи команды COPY
ПараметрОписание
источникИмя копируемого файла или файлов
/AФайл является текстовым файлом ASCII, то есть конец файла обозначается символом с кодом ASCII 26 (<Ctrl>+<Z>)
/BФайл является двоичным. Этот ключ указывает на то, что интерпретатор команд должен при копировании считывать из источника число байт, заданное размером в каталоге копируемого файла
результатКаталог для размещения результата копирования и/или имя создаваемого файла
/VПроверка правильности копирования путем сравнения файлов после копирования
/YОтключение режима запроса подтверждения на замену файлов
/-YВключение режима запроса подтверждения на замену файлов

Приведем примеры использования команды COPY.

  1. Копирование файла abc.txt из текущего каталога в каталог D:\PROGRAM под тем же именем:
    COPY abc.txt D:\PROGRAM
  2. Копирование файла abc.txt из текущего каталога в каталог D:\PROGRAM под новым именем def.txt:
    COPY abc.txt D:\PROGRAM\def.txt
  3. Копирование всех файлов с расширением txt с диска A: в каталог 'Мои документы' на диске C:
    COPY A:\*.txt "C:\Мои документы"

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

COPY A:\*.*

В качестве источника или результата при копировании можно указывать имена не только файлов, но и устройств компьютера. Например, для того, чтобы распечатать файл abc.txt на принтере, можно воспользоваться командой копирования этого файла на устройство PRN: COPY abc.txt PRN

Другой интересный пример: создадим новый текстовый файл и запишем в него информацию, без использования текстового редактора. Для этого достаточно ввести команду COPY CON my.txt, которая будет копировать то, что вы набираете на клавиатуре, в файл my.txt (если этот файл существовал, то он перезапишется, иначе — создастся). Для завершения ввода необходимо ввести символ конца файла, то есть нажать клавиши <Ctrl>+<Z>.

Команда COPY может также объединять (склеивать) несколько файлов в один. Для этого необходимо указать единственный результирующий файл и несколько исходных. Это достигается путем использования групповых знаков (? и *) или формата файл1 + файл2 + файл3. Например, для объединения файлов 1.txt и 2.txt в файл 3.txt можно задать следующую команду:

COPY 1.txt+2.txt 3.txt

Объединение всех файлов с расширением dat из текущего каталога в один файл all.dat может быть произведено так:

COPY /B *.dat all.dat

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

Если имя целевого файла совпадает с именем одного из копируемых файлов (кроме первого), то исходное содержимое целевого файла теряется. Если имя целевого файла опущено, то в его качестве используется первый файл из списка. Например, команда COPY 1.txt+2.txt добавит к содержимому файла 1.txt содержимое файла 2.txt. Командой COPY можно воспользоваться и для присвоения какому-либо файлу текущей даты и времени без модификации его содержимого. Для этого нужно ввести команду типа

COPY /B 1.txt +,,

Здесь запятые указывают на пропуск параметра приемника, что и приводит к требуемому результату.

Команда COPY имеет и свои недостатки. Например, с ее помощью нельзя копировать скрытые и системные файлы, файлы нулевой длины, файлы из подкаталогов. Кроме того, если при копировании группы файлов COPY встретит файл, который в данный момент нельзя скопировать (например, он занят другим приложением), то процесс копирования полностью прервется, и остальные файлы не будут скопированы.

Команда XCOPY

Указанные при описании команды COPY проблемы можно решить с помощью команды XCOPY, которая предоставляет намного больше возможностей при копировании. Необходимо отметить, правда, что XCOPY может работать только с файлами и каталогами, но не с устройствами.

Синтаксис этой команды:

XCOPY источник [результат] [ключи]

Команда XCOPY имеет множество ключей, мы коснемся лишь некоторых из них. Ключ /D[:[дата]] позволяет копировать только файлы, измененные не ранее указанной даты. Если параметр дата не указан, то копирование будет производиться только если источник новее результата. Например, команда

XCOPY "C:\Мои документы\*.*" "D:\BACKUP\Мои документы" /D

скопирует в каталог 'D:\BACKUP\Мои документы' только те файлы из каталога 'C:\Мои документы', которые были изменены со времени последнего подобного копирования или которых вообще не было в 'D:\BACKUP\Мои документы'.

Ключ /S позволяет копировать все непустые подкаталоги в каталоге-источнике. С помощью же ключа /E можно копировать вообще все подкаталоги, включая и пустые.

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

Ключ /I важен для случая, когда копируются несколько файлов, а файл назначения отсутствует. При задании этого ключа команда XCOPY считает, что файл назначения должен быть каталогом. Например, если задать ключ /I в команде копирования всех файлов с расширением txt из текущего каталога в несуществующий еще подкаталог TEXT,

XCOPY  *.txt TEXT /I

то подкаталог TEXT будет создан без дополнительных запросов.

Ключи /Q, /F и /L отвечают за режим отображения при копировании. При задании ключа /Q имена файлов при копировании не отображаются, ключа /F — отображаются полные пути источника и результата. Ключ /L обозначает, что отображаются только файлы, которые должны быть скопированы (при этом само копирование не производится).

С помощью ключа /H можно копировать скрытые и системные файлы, а с помощью ключа /R — заменять файлы с атрибутом "Только для чтения". Например, для копирования всех файлов из корневого каталога диска C: (включая системные и скрытые) в каталог SYS на диске D:, нужно ввести следующую команду:

XCOPY C:\*.* D:\SYS /H

Ключ /T позволяет применять XCOPY для копирования только структуры каталогов источника, без дублирования находящихся в этих каталогах файлов, причем пустые каталоги и подкаталоги не включаются. Для того, чтобы все же включить пустые каталоги и подкаталоги, нужно использовать комбинацию ключей /T /E.

Используя XCOPY можно при копировании обновлять только уже существующие файлы (новые файлы при этом не записываются). Для этого применяется ключ /U. Например, если в каталоге C:\2 находились файлы a.txt и b.txt, а в каталоге C:\1 — файлы a.txt, b.txt, c.txt и d.txt, то после выполнения команды

XCOPY C:\1 C:\2 /U

в каталоге C:\2 по-прежнему останутся лишь два файла a.txt и b.txt, содержимое которых будет заменено содержимым соответствующих файлов из каталога C:\1.Если с помощью XCOPY копировался файл с атрибутом "Только для чтения", то по умолчанию у файла-копии этот атрибут снимется. Для того, чтобы копировать не только данные, но и полностью атрибуты файла, необходимо использовать ключ /K.

Ключи /Y и /-Y определяют, нужно ли запрашивать подтверждение перед заменой файлов при копировании. /Y — подавление запроса подтверждения на перезапись существующего целевого файла, /-Y — запрос подтверждения на перезапись существующего целевого файла.

Команда DIR

Еще одной очень полезной командой является DIR [диск:][путь][имя_файла] [ключи], которая используется для вывода информации о содержимом дисков и каталогов. Параметр [диск:][путь] задает диск и каталог, содержимое которого нужно вывести на экран. Параметр [имя_файла] задает файл или группу файлов, которые нужно включить в список. Например, команда

DIR C:\*.bat

выведет на экран все файлы с расширением bat в корневом каталоге диска C:. Если задать эту команду без параметров, то выводится метка диска и его серийный номер, имена (в коротком и длинном вариантах) файлов и подкаталогов, находящихся в текущем каталоге, а также дата и время их последней модификации. После этого выводится число файлов в каталоге, общий объем (в байтах), занимаемый файлами, и объем свободного пространства на диске. Например:

Том в устройстве C имеет метку PHYS1_PART2
 Серийный номер тома: 366D-6107
 Содержимое папки C:\aditor
.              <ПАПКА>      25.01.00  17:15 .
..             <ПАПКА>      25.01.00  17:15 ..
TEMPLT02 DAT           227  07.08.98   1:00 templt02.dat
UNINST1  000         1 093  02.03.99   8:36 UNINST1.000
HILITE   DAT         1 082  18.09.98  18:55 hilite.dat
TEMPLT01 DAT            48  07.08.98   1:00 templt01.dat
UNINST0  000        40 960  15.04.98   2:08 UNINST0.000
TTABLE   DAT           357  07.08.98   1:00 ttable.dat
ADITOR   EXE       461 312  01.12.99  23:13 aditor.exe
README   TXT         3 974  25.01.00  17:26 readme.txt
ADITOR   HLP        24 594  08.10.98  23:12 aditor.hlp
ТЕКСТО~1 TXT             0  11.03.01   9:02 Текстовый файл.txt
        11 файлов        533 647 байт
         2 папок     143 261 696 байт свободно

С помощью ключей команды DIR можно задать различные режимы расположения, фильтрации и сортировки. Например, при использовании ключа /W перечень файлов выводится в широком формате с максимально возможным числом имен файлов или каталогов на каждой строке. Например:

Том в устройстве C имеет метку PHYS1_PART2
 Серийный номер тома: 366D-6107
 Содержимое папки C:\aditor
[.]           	[..]          	TEMPLT02.DAT	UNINST1.000 	HILITE.DAT  
TEMPLT01.DAT	UNINST0.000 	TTABLE.DAT  	ADITOR.EXE  	README.TXT  
ADITOR.HLP  	ТЕКСТО~1.TXT
        11 файлов        533 647 байт
         2 папок     143 257 600 байт свободно

С помощью ключа /A[[:]атрибуты] можно вывести имена только тех каталогов и файлов, которые имеют заданные атрибуты ( R — "Только чтение", A — "Архивный", S — "Системный", H — "Скрытый", префикс "–" имеет значение НЕ). Если ключ /A используется более чем с одним значением атрибута, будут выведены имена только тех файлов, у которых все атрибуты совпадают с заданными. Например, для вывода имен всех файлов в корневом каталоге диска C:, которые одновременно являются скрытыми и системными, можно задать команду

DIR C:\ /A:HS

а для вывода всех файлов, кроме скрытых — команду

DIR C:\ /A:-H

Отметим здесь, что атрибуту каталога соответствует буква D, то есть для того, чтобы, например, вывести список всех каталогов диска C:, нужно задать команду

DIR C: /A:D

Ключ /O[[:]сортировка] задает порядок сортировки содержимого каталога при выводе его командой DIR. Если этот ключ опущен, DIR печатает имена файлов и каталогов в том порядке, в котором они содержатся в каталоге. Если ключ /O задан, а параметр сортировка не указан, то DIR выводит имена в алфавитном порядке. В параметре сортировка можно использовать следующие значения: N — по имени (алфавитная), S — по размеру (начиная с меньших), E — по расширению (алфавитная), D — по дате (начиная с более старых), A — по дате загрузки (начиная с более старых), G — начать список с каталогов. Префикс "–" означает обратный порядок. Если задается более одного значения порядка сортировки, файлы сортируются по первому критерию, затем по второму и т.д.

Ключ /S означает вывод списка файлов из заданного каталога и его подкаталогов.

Ключ /B перечисляет только названия каталогов и имена файлов (в длинном формате) по одному на строку, включая расширение. При этом выводится только основная информация, без итоговой. Например:

templt02.dat
UNINST1.000
hilite.dat
templt01.dat
UNINST0.000
ttable.dat
aditor.exe
readme.txt
aditor.hlp
Текстовый файл.txt
Команды MKDIR и RMDIR

Для создания нового каталога и удаления уже существующего пустого каталога используются команды MKDIR [диск:]путь и RMDIR [диск:]путь [ключи] соответственно (или их короткие аналоги MD и RD ). Например:

MKDIR "C:\Примеры" 
RMDIR "C:\Примеры"

Команда MKDIR не может быть выполнена, если каталог или файл с заданным именем уже существует. Команда RMDIR не будет выполнена, если удаляемый каталог не пустой.

Команда DEL

Удалить один или несколько файлов можно с помощью команды

DEL [диск:][путь]имя_файла [ключи]

Для удаления сразу нескольких файлов используются групповые знаки ? и *. Ключ /S позволяет удалить указанные файлы из всех подкаталогов, ключ /F – принудительно удалить файлы, доступные только для чтения, ключ /A[[:]атрибуты] – отбирать файлы для удаления по атрибутам (аналогично ключу /A[[:]атрибуты] в команде DIR ).

Команда REN

Переименовать файлы и каталоги можно с помощью команды RENAME ( REN ). Синтаксис этой команды имеет следующий вид:

REN [диск:][путь][каталог1|файл1] [каталог2|файл2]

Здесь параметр каталог1|файл1 определяет название каталога/файла, которое нужно изменить, а каталог2|файл2 задает новое название каталога/файла. В любом параметре команды REN можно использовать групповые символы ? и *. При этом представленные шаблонами символы в параметре файл2 будут идентичны соответствующим символам в параметре файл1. Например, чтобы изменить у всех файлов с расширением txt в текущей директории расширение на doc, нужно ввести такую команду:

REN *.txt *.doc

Если файл с именем файл2 уже существует, то команда REN прекратит выполнение, и произойдет вывод сообщения, что файл уже существует или занят. Кроме того, в команде REN нельзя указать другой диск или каталог для создания результирующих каталога и файла. Для этой цели нужно использовать команду MOVE, предназначенную для переименования и перемещения файлов и каталогов.

Команда MOVE

Синтаксис команды для перемещения одного или более файлов имеет вид:

MOVE [/Y|/–Y] [диск:][путь]имя_файла1[,...] результирующий_файл

Синтаксис команды для переименования папки имеет вид:

MOVE [/Y|/–Y] [диск:][путь]каталог1 каталог2

Здесь параметр результирующий_файл задает новое размещение файла и может включать имя диска, двоеточие, имя каталога, либо их сочетание. Если перемещается только один файл, допускается указать его новое имя. Это позволяет сразу переместить и переименовать файл. Например,

MOVE "C:\Мои документы\список.txt" D:\list.txt

Если указан ключ /-Y, то при создании каталогов и замене файлов будет выдаваться запрос на подтверждение. Ключ /Y отменяет выдачу такого запроса.

Лекция 3. Язык интерпретатора Cmd.exe. Командные файлы

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

Язык интерпретатора Cmd.exe. Командные файлы

Язык оболочки командной строки (shell language) в Windows реализован в виде командных (или пакетных) файлов. Командный файл в Windows — это обычный текстовый файл с расширением bat или cmd, в котором записаны допустимые команды операционной системы (как внешние, так и внутренние), а также некоторые дополнительные инструкции и ключевые слова, придающие командным файлам некоторое сходство с алгоритмическими языками программирования. Например, если записать в файл deltmp.bat следующие команды:

C:\
CD %TEMP%
DEL /F *.tmp

и запустить его на выполнение (аналогично исполняемым файлам с расширением com или exe), то мы удалим все файлы во временной директории Windows. Таким образом, исполнение командного файла приводит к тому же результату, что и последовательный ввод записанных в нем команд. При этом не проводится никакой предварительной компиляции или проверки синтаксиса кода; если встречается строка с ошибочной командой, то она игнорируется. Очевидно, что если вам приходится часто выполнять одни и те же действия, то использование командных файлов может сэкономить много времени.

Вывод сообщений и дублирование команд

По умолчанию команды пакетного файла перед исполнением выводятся на экран, что выглядит не очень эстетично. С помощью команды ECHO OFF можно отключить дублирование команд, идущих после нее (сама команда ECHO OFF при этом все же дублируется). Например,

REM Следующие две команды будут дублироваться на экране …
DIR C:\
ECHO OFF
REM А остальные уже не будут
DIR D:\

Для восстановления режима дублирования используется команда ECHO ON. Кроме этого, можно отключить дублирование любой отдельной строки в командном файле, написав в начале этой строки символ @, например:

ECHO ON
REM Команда DIR C:\ дублируется на экране
DIR C:\
REM А команда DIR D:\ — нет
@DIR D:\

Таким образом, если поставить в самое начало файла команду

@ECHO OFF

то это решит все проблемы с дублированием команд.

В пакетном файле можно выводить на экран строки с сообщениями. Делается это с помощью команды

ECHO сообщение

Например,

@ECHO OFF
ECHO Привет!

Команда ECHO. (точка должна следовать непосредственно за словом "ECHO") выводит на экран пустую строку. Например,

@ECHO OFF
ECHO Привет!
ECHO.
ECHO Пока!

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

Используя механизм перенаправления ввода/вывода (символы > и >>), можно направить сообщения, выводимые командой ECHO, в определенный текстовый файл. Например:

@ECHO OFF
ECHO Привет! > hi.txt
ECHO Пока! >> hi.txt

С помощью такого метода можно, скажем, заполнять файлы-протоколы с отчетом о произведенных действиях. Например:

@ECHO OFF
REM Попытка копирования
XCOPY C:\PROGRAMS D:\PROGRAMS /s
REM Добавление сообщения в файл report.txt в случае
REM удачного завершения копирования
IF NOT ERRORLEVEL 1 ECHO Успешное копирование >> report.txt

Использование параметров командной строки

При запуске пакетных файлов в командной строке можно указывать произвольное число параметров, значения которых можно использовать внутри файла. Это позволяет, например, применять один и тот же командный файл для выполнения команд с различными параметрами.

Для доступа из командного файла к параметрам командной строки применяются символы %0, %1, …, %9 или %*. При этом вместо %0 подставляется имя выполняемого пакетного файла, вместо %1, %2, …, %9 — значения первых девяти параметров командной строки соответственно, а вместо %* — все аргументы. Если в командной строке при вызове пакетного файла задано меньше девяти параметров, то "лишние" переменные из %1 – %9 замещаются пустыми строками. Рассмотрим следующий пример. Пусть имеется командный файл copier.bat следующего содержания:

@ECHO OFF
CLS
ECHO Файл %0 копирует каталог %1 в %2
XCOPY %1 %2 /S

Если запустить его из командной строки с двумя параметрами, например

copier.bat C:\Programs D:\Backup

то на экран выведется сообщение

Файл copier.bat копирует каталог C:\Programs в D:\Backup

и произойдет копирование каталога C:\Programs со всеми его подкаталогами в D:\Backup.

При необходимости можно использовать более девяти параметров командной строки. Это достигается с помощью команды SHIFT, которая изменяет значения замещаемых параметров с %0 по %9, копируя каждый параметр в предыдущий, то есть значение %1 копируется в %0, значение %2 – в %1 и т.д. Замещаемому параметру %9 присваивается значение параметра, следующего в командной строке за старым значением %9. Если же такой параметр не задан, то новое значение %9 — пустая строка.

Рассмотрим пример. Пусть командный файл my.bat вызван из командной строки следующим образом:

my.bat p1 p2 p3

Тогда %0=my.bat, %1=p1, %2=p2, %3=p3, параметры %4 – %9 являются пустыми строками. После выполнения команды SHIFT значения замещаемых параметров изменятся следующим образом: %0=p1, %1=p2, %2=p3, параметры %3 – %9 – пустые строки.

При включении расширенной обработки команд SHIFT поддерживает ключ /n, задающий начало сдвига параметров с номера n, где n может быть числом от 0 до 9.

Например, в следующей команде:

SHIFT /2

параметр %2 заменяется на %3, %3 на %4 и т.д., а параметры %0 и %1 остаются без изменений.

Команда, обратная SHIFT (обратный сдвиг), отсутствует. После выполнения SHIFT уже нельзя восстановить параметр (%0), который был первым перед сдвигом. Если в командной строке задано больше десяти параметров, то команду SHIFT можно использовать несколько раз.

В командных файлах имеются некоторые возможности синтаксического анализа заменяемых параметров. Для параметра с номером n (%n) допустимы синтаксические конструкции (операторы), представленные в табл. 3.1.

Таблица 3.1. Операторы для заменяемых параметров
ОператорыОписание
%~FnПеременная %n расширяется до полного имени файла
%~DnИз переменной %n выделяется только имя диска
%~PnИз переменной %n выделяется только путь к файлу
%~NnИз переменной %n выделяется только имя файла
%~XnИз переменной %n выделяется расширение имени файла
%~SnЗначение операторов N и X для переменной %n изменяется так, что они работают с кратким именем файла
%~$PATH:nПроводится поиск по каталогам, заданным в переменной среды PATH, и переменная %n заменяется на полное имя первого найденного файла. Если переменная PATH не определена или в результате поиска не найден ни один файл, эта конструкция заменяется на пустую строку. Естественно, здесь переменную PATH можно заменить на любое другое допустимое значение

Данные синтаксические конструкции можно объединять друг с другом, например:

%~DPn — из переменной %n выделяется имя диска и путь,

%~NXn — из переменной %n выделяется имя файла и расширение.

Рассмотрим следующий пример. Пусть мы находимся в каталоге C:\TEXT и запускаем пакетный файл с параметром Рассказ.doc ( %1=Рассказ.doc ). Тогда применение операторов, описанных в табл. 3.1, к параметру %1 даст следующие результаты:

%~F1=C:\TEXT\Рассказ.doc
%~D1=C:
%~P1=\TEXT\
%~N1=Рассказ
%~X1=.doc
%~DP1=C:\TEXT\
%~NX1=Рассказ.doc

Работа с переменными среды

Внутри командных файлов можно работать с так называемыми переменными среды (или переменными окружения), каждая из которых хранится в оперативной памяти, имеет свое уникальное имя, а ее значением является строка. Стандартные переменные среды автоматически инициализируются в процессе загрузки операционной системы. Такими переменными являются, например, WINDIR, которая определяет расположение каталога Windows, TEMP, которая определяет путь к каталогу для хранения временных файлов Windows или PATH, в которой хранится системный путь (путь поиска), то есть список каталогов, в которых система должна искать выполняемые файлы или файлы совместного доступа (например, динамические библиотеки). Кроме того, в командных файлах с помощью команды SET можно объявлять собственные переменные среды.

Получение значения переменной

Для получения значения определенной переменной среды нужно имя этой переменной заключить в символы %. Например:

@ECHO OFF
CLS
REM Создание переменной MyVar
SET MyVar=Привет
REM Изменение переменной
SET MyVar=%MyVar%!
ECHO Значение переменной MyVar: %MyVar% 
REM Удаление переменной MyVar
SET MyVar=
ECHO Значение переменной WinDir: %WinDir%

При запуске такого командного файла на экран выведется строка

Значение переменной MyVar: Привет!
Значение переменной WinDir: C:\WINDOWS
Преобразования переменных как строк

С переменными среды в командных файлах можно производить некоторые манипуляции. Во-первых, над ними можно производить операцию конкатенации (склеивания). Для этого нужно в команде SET просто написать рядом значения соединяемых переменных. Например,

SET A=Раз
SET B=Два
SET C=%A%%B%

После выполнения в файле этих команд значением переменной C будет являться строка 'РазДва'. Не следует для конкатенации использовать знак +, так как он будет воспринят просто в качестве символа. Например, после запуска файла следующего содержания

SET A=Раз
SET B=Два
SET C=A+B
ECHO Переменная C=%C%
SET D=%A%+%B%
ECHO Переменная D=%D%

на экран выведутся две строки:

Переменная C=A+B
Переменная D=Раз+Два

Во-вторых, из переменной среды можно выделять подстроки с помощью конструкции %имя_переменной:~n1,n2%, где число n1 определяет смещение (количество пропускаемых символов) от начала (если n1 положительно) или от конца (если n1 отрицательно) соответствующей переменной среды, а число n2 – количество выделяемых символов (если n2 положительно) или количество последних символов в переменной, которые не войдут в выделяемую подстроку (если n2 отрицательно). Если указан только один отрицательный параметр -n, то будут извлечены последние n символов. Например, если в переменной %DATE% хранится строка "21.09.2007" (символьное представление текущая дата при определенных региональных настройках), то после выполнения следующих команд

SET dd1=%DATE:~0,2%
SET dd2=%DATE:~0,-8%
SET mm=%DATE:~-7,2%
SET yyyy=%DATE:~-4%

новые переменные будут иметь такие значения: %dd1%=21, %dd2%=21, %mm%=09, %yyyy%=2007.

В-третьих, можно выполнять процедуру замены подстрок с помощью конструкции %имя_переменной:s1=s2% (в результате будет возвращена строка, в которой каждое вхождение подстроки s1 в соответствующей переменной среды заменено на s2 ). Например, после выполнения команд

SET a=123456
SET b=%a:23=99%

в переменной b будет храниться строка "199456". Если параметр s2 не указан, то подстрока s1 будет удалена из выводимой строки, т.е. после выполнения команды

SET a=123456
SET b=%a:23=%

в переменной b будет храниться строка "1456".

Операции с переменными как с числами

При включенной расширенной обработке команд (этот режим в Windows XP используется по умолчанию) имеется возможность рассматривать значения переменных среды как числа и производить с ними арифметические вычисления. Для этого используется команда SET с ключом /A. Приведем пример пакетного файла add.bat, складывающего два числа, заданных в качестве параметров командной строки, и выводящего полученную сумму на экран:

@ECHO OFF
REM В переменной M будет храниться сумма
SET /A M=%1+%2
ECHO Сумма %1 и %2 равна %M%
REM Удалим переменную M
SET M=
Локальные изменения переменных

Все изменения, производимые с помощью команды SET над переменными среды в командном файле, сохраняются и после завершения работы этого файла, но действуют только внутри текущего командного окна. Также имеется возможность локализовать изменения переменных среды внутри пакетного файла, то есть автоматически восстанавливать значения всех переменных в том виде, в каком они были до начала запуска этого файла. Для этого используются две команды: SETLOCAL и ENDLOCAL. Команда SETLOCAL определяет начало области локальных установок переменных среды. Другими словами, изменения среды, внесенные после выполнения SETLOCAL, будут являться локальными относительно текущего пакетного файла. Каждая команда SETLOCAL должна иметь соответствующую команду ENDLOCAL для восстановления прежних значений переменных среды. Изменения среды, внесенные после выполнения команды ENDLOCAL, уже не являются локальными относительно текущего пакетного файла; их прежние значения не будут восстановлены по завершении выполнения этого файла.

Связывание времени выполнения для переменных

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

SET a=1
ECHO a=%a% 
SET a=2
ECHO a=%a%

и командный файл 2.bat:

SET a=1
ECHO a=%a% 
(SET a=2
ECHO a=%a% )

Казалось бы, результат выполнения этих двух файлов должен быть одинаковым: на экран выведутся две строки: "a=1" и "a=2". На самом же деле таким образом сработает только файл 1.bat, а файл 2.bat два раза выведет строку "a=1"!

Данную ошибку можно обойти, если для получения значения переменной вместо знаков процента (%) использовать восклицательный знак (!) и предварительно включить режим связывания времени выполнения командой SETLOCAL ENABLEDELAYEDEXPANSION. Таким образом, для корректной работы файл 2.bat должен иметь следующий вид:

SETLOCAL ENABLEDELAYEDEXPANSION 
SET a=1
ECHO a=%a% 
(SET a=2
ECHO a=!a! )

Приостановка выполнения командных файлов

Для того, чтобы вручную прервать выполнение запущенного bat-файла, нужно нажать клавиши <Ctrl>+<C> или <Ctrl>+<Break>. Однако часто бывает необходимо программно приостановить выполнение командного файла в определенной строке с выдачей запроса на нажатие любой клавиши. Это делается с помощью команды PAUSE. Перед запуском этой команды полезно с помощью команды ECHO информировать пользователя о действиях, которые он должен произвести. Например:

ECHO Вставьте дискету в дисковод A: и нажмите любую клавишу
PAUSE

Команду PAUSE обязательно нужно использовать при выполнении потенциально опасных действий (удаление файлов, форматирование дисков и т.п.). Например,

ECHO Сейчас будут удалены все файлы в C:\Мои документы!
ECHO Для отмены нажмите Ctrl-C
PAUSE
DEL "C:\Мои документы\*.*"

Вызов внешних командных файлов

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

@ECHO OFF
CLS
REM Вывод списка log-файлов
DIR C:\*.log
REM Передача выполнения файлу f.bat
f.bat
COPY A:\*.* C:\
PAUSE

Однако в этом случае после выполнения вызванного файла управление в вызывающий файл не передается, то есть в приведенном примере команда

COPY A:\*.* C:\

(и все следующие за ней команды) никогда не будет выполнена.

Для того, чтобы вызвать внешний командный файл с последующим возвратом в первоначальный файл, нужно использовать специальную команду CALL файл

Например:

@ECHO OFF
CLS
REM Вывод списка log-файлов
DIR C:\*.log
REM Передача выполнения файлу f.bat
CALL f.bat
COPY A:\*.* C:\
PAUSE

В этом случае после завершения работы файла f.bat управление вернется в первоначальный файл на строку, следующую за командой CALL (в нашем примере это команда COPY A:\*.* C:\ ).

Операторы перехода

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

Пусть имеется командный файл следующего содержания:

@ECHO OFF
COPY %1 %2
GOTO Label1
ECHO Эта строка никогда не выполнится
:Label1
REM Продолжение выполнения
DIR %2

После того, как в этом файле мы доходим до команды

GOTO Label1

его выполнение продолжается со строки

REM Продолжение выполнения

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

Также для перехода к метке внутри текущего командного файла кроме команды GOTO можно использовать и рассмотренную выше команду CALL:

CALL :метка аргумента

При вызове такой команды создается новый контекст текущего пакетного файла с заданными аргументами, и управление передается на инструкцию, расположенную сразу после метки. Для выхода из такого пакетного файла необходимо два раза достичь его конца. Первый выход возвращает управление на инструкцию, расположенную сразу после строки CALL, а второй выход завершает выполнение пакетного файла. Например, если запустить с параметром "Копия-1" командный файл следующего содержания:

@ECHO OFF
ECHO %1
CALL :2 Копия-2
:2
ECHO %1

то на экран выведутся три строки:

Копия-1
Копия-2
Копия-1

Таким образом, подобное использование команды CALL очень похоже на обычный вызов подпрограмм (процедур) в алгоритмических языках программирования.

Операторы условия

С помощью команды IF … ELSE (ключевое слово ELSE может отсутствовать) в пакетных файлах можно выполнять обработку условий нескольких типов. При этом если заданное после IF условие принимает истинное значение, система выполняет следующую за условием команду (или несколько команд, заключенных в круглые скобки), в противном случае выполняется команда (или несколько команд в скобках), следующие за ключевым словом ELSE.

Проверка значения переменной

Первый тип условия используется обычно для проверки значения переменной. Для этого применяются два варианта синтаксиса команды IF:

IF [NOT] строка1==строка2 команда1 [ELSE команда2]

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

IF [/I] [NOT] строка1 оператор_сравнения строка2 команда

Рассмотрим сначала первый вариант. Условие строка1==строка2 (здесь необходимо писать именно два знака равенства) считается истинным при точном совпадении обеих строк. Параметр NOT указывает на то, что заданная команда выполняется лишь в том случае, когда сравниваемые строки не совпадают.

Строки могут быть литеральными или представлять собой значения переменных (например, %1 или %TEMP% ). Кавычки для литеральных строк не требуются. Например,

IF %1==%2 ECHO Параметры совпадают!
IF %1==Петя ECHO Привет, Петя!

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

IF %MyVar%==C:\ ECHO Ура!!!

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

IF -%MyVar%==-C:\ ECHO Ура!!!

С помощью команд IF и SHIFT можно в цикле обрабатывать все параметры командной строки файла, даже не зная заранее их количества. Например, следующий командный файл (назовем его primer.bat) выводит на экран имя запускаемого файла и все параметры командной строки:

@ECHO OFF
ECHO Выполняется файл: %0
ECHO.
ECHO Файл запущен со следующими параметрами...
REM Начало цикла
:BegLoop
IF -%1==- GOTO ExitLoop
ECHO %1
REM Сдвиг параметров
SHIFT
REM Переход на начало цикла
GOTO BegLoop
:ExitLoop
REM Выход из цикла
ECHO.
ECHO Все.

Если запустить primer.bat с четырьмя параметрами:

primer.bat А Б В Г

то в результате выполнения на экран выведется следующая информация:

Выполняется файл: primer.bat

Файл запущен со следующими параметрами:
А
Б
В
Г

Все.

Рассмотрим теперь оператор IF в следующем виде:

IF [/I] строка1 оператор_сравнения строка2 команда

Синтаксис и значение операторов_сравнения представлены в табл. 3.2.

Таблица 3.2. Операторы сравнения в IF
ОператорЗначение
EQLРавно
NEQНе равно
LSSМеньше
LEQМеньше или равно
GTRБольше
GEQБольше или равно

Приведем пример использования операторов сравнения:

@ECHO OFF
CLS
IF -%1 EQL –Вася ECHO Привет, Вася!
IF -%1 NEQ –Вася ECHO Привет, но Вы не Вася!

Ключ /I, если он указан, задает сравнение текстовых строк без учета регистра. Ключ /I можно также использовать и в форме строка1==строка2 команды IF. Например, условие

IF /I DOS==dos …

будет истинным.

Проверка существования заданного файла

Второй способ использования команды IF — это проверка существования заданного файла. Синтаксис для этого случая имеет вид:

IF [NOT] EXIST файл команда1 [ELSE команда2]

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

@ECHO OFF
IF -%1==- GOTO NoFileSpecified
IF NOT EXIST %1 GOTO FileNotExist

REM Вывод сообщения о найденном файле
ECHO Файл '%1' успешно найден.
GOTO :EOF

:NoFileSpecified
REM Файл запущен без параметров
ECHO В командной строке не указано имя файла.
GOTO :EOF

:FileNotExist
REM Параметр командной строки задан, но файл не найден
ECHO Файл '%1' не найден.
Проверка наличия переменной среды

Аналогично файлам команда IF позволяет проверить наличие в системе определенной переменной среды:

IF DEFINED переменная команда1 [ELSE команда2]

Здесь условие DEFINED применяется подобно условию EXISTS наличия заданного файла, но принимает в качестве аргумента имя переменной среды и возвращает истинное значение, если эта переменная определена. Например:

@ECHO OFF
CLS
IF DEFINED MyVar GOTO :VarExists
ECHO Переменная MyVar не определена
GOTO :EOF
:VarExists
ECHO Переменная MyVar определена,
ECHO ее значение равно %MyVar%
Проверка кода завершения предыдущей команды

Еще один способ использования команды IF — это проверка кода завершения (кода выхода) предыдущей команды. Синтаксис для IF в этом случае имеет следующий вид:

IF [NOT] ERRORLEVEL число команда1 [ELSE команда2]

Здесь условие считается истинным, если последняя запущенная команда или программа завершилась с кодом возврата, равным либо превышающим указанное число.

Составим, например, командный файл, который бы копировал файл my.txt на диск C: без вывода на экран сообщений о копировании, а в случае возникновения какой-либо ошибки выдавал предупреждение:

@ECHO OFF
XCOPY my.txt C:\ > NUL
REM Проверка кода завершения копирования
IF ERRORLEVEL 1 GOTO ErrOccurred
ECHO Копирование выполнено без ошибок.
GOTO :EOF

:ErrOccurred
ECHO При выполнении команды XCOPY возникла ошибка!

В операторе IF ERRORLEVEL … можно также применять операторы сравнения чисел, приведенные в табл. 3.2. Например:

IF ERRORLEVEL LEQ 1 GOTO Case1

Замечание.

Иногда более удобным для работы с кодами завершения программ может оказаться использование переменной %ERRORLEVEL%. (строковое представление текущего значения кода ошибки ERRORLEVEL ).

Проверка версии реализации расширенной обработки команд

Наконец, для определения внутреннего номера версии текущей реализации расширенной обработки команд применяется оператор IF в следующем виде:

IF CMDEXTVERSION число команда1 [ELSE команда2]

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

Организация циклов

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

Цикл FOR … IN … DO …

Самый простой вариант синтаксиса команды FOR для командных файлов имеет следующий вид:

FOR %%переменная IN (множество) 
 DO команда [параметры]

Внимание

Перед названием переменной должны стоять именно два знака процента (%%), а не один, как это было при использовании команды FOR непосредственно из командной строки.

Сразу приведем пример. Если в командном файле заданы строки

@ECHO OFF
FOR %%i IN (Раз,Два,Три) DO ECHO %%i

то в результате его выполнения на экране будет напечатано следующее:

Раз
Два
Три

Параметр множество в команде FOR задает одну или более текстовых строк, разделенных запятыми, которые вы хотите обработать с помощью заданной команды. Скобки здесь обязательны. Параметр команда [параметры] задает команду, выполняемую для каждого элемента множества, при этом вложенность команд FOR на одной строке не допускается. Если в строке, входящей во множество, используется запятая, то значение этой строки нужно заключить в кавычки. Например, в результате выполнения файла с командами

@ECHO OFF
FOR %%i IN ("Раз,Два",Три) DO ECHO %%i

на экран будет выведено

Раз,Два
Три

Параметр %%переменная представляет подставляемую переменную (счетчик цикла), причем здесь могут использоваться только имена переменных, состоящие из одной буквы. При выполнении команда FOR заменяет подставляемую переменную текстом каждой строки в заданном множестве, пока команда, стоящая после ключевого слова DO, не обработает все такие строки.

Замечание.

Чтобы избежать путаницы с параметрами командного файла %0 — %9, для переменных следует использовать любые символы кроме 0 – 9.

Параметр множество в команде FOR может также представлять одну или несколько групп файлов. Например, чтобы вывести в файл список всех файлов с расширениями txt и prn, находящихся в каталоге C:\TEXT, без использования команды DIR, можно использовать командный файл следующего содержания:

@ECHO OFF
FOR %%f IN (C:\TEXT\*.txt C:\TEXT\*.prn) DO ECHO %%f >> list.txt

При таком использовании команды FOR процесс обработки продолжается, пока не обработаются все файлы (или группы файлов), указанные во множестве.

Цикл FOR /D … IN … DO …

Следующий вариант команды FOR реализуется с помощью ключа /D:

FOR /D %%переменная IN (набор) DO команда [параметры]

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

@ECHO OFF
CLS
FOR /D %%f IN (C:\*.*) DO ECHO %%f

мы получим список всех каталогов на диске C:, например:

C:\Arc
C:\CYR
C:\MSCAN
C:\NC
C:\Program Files
C:\TEMP
C:\TeX
C:\WINNT
Цикл FOR /R … IN … DO …

С помощью ключа /R можно задать рекурсию в команде: FOR:

FOR /R [[диск:]путь] %%переменная IN (набор) 
  DO команда [параметры]

В этом случае заданная команда выполняется для каталога [диск:]путь, а также для всех подкаталогов этого пути. Если после ключа R не указано имя каталога, то выполнение команды начинается с текущего каталога. Например, для распечатки всех файлов с расширением txt в текущем каталоге и всех его подкаталогах можно использовать следующий пакетный файл:

@ECHO OFF
CLS
FOR /R %%f IN (*.txt) DO PRINT %%f

Если вместо набора указана только точка (.), то команда проверяет все подкаталоги текущего каталога. Например, если мы находимся в каталоге C:\TEXT с двумя подкаталогами BOOKS и ARTICLES, то в результате выполнения файла:

@ECHO OFF
CLS
FOR /R %%f IN (.) DO ECHO %%f
на экран выведутся три строки:
C:\TEXT\.
C:\TEXT\BOOKS\.
C:\TEXT\ARTICLES\.
Цикл FOR /L … IN … DO …

Ключ /L позволяет реализовать с помощью команды FOR арифметический цикл, в этом случае синтаксис имеет следующий: вид:

FOR /L %%переменная IN (начало,шаг,конец) DO команда [параметры]

Здесь заданная после ключевого слова IN тройка (начало,шаг,конец) раскрывается в последовательность чисел с заданными началом, концом и шагом приращения. Так, набор (1,1,5) раскрывается в (1 2 3 4 5), а набор (5,-1,1) заменяется на (5 4 3 2 1). Например, в результате выполнения следующего командного файла:

@ECHO OFF
CLS
FOR /L %%f IN (1,1,5) DO ECHO %%f

переменная цикла %%f пробежит значения от 1 до 5, и на экране напечатаются пять чисел:

1
2
3
4
5

Числа, получаемые в результате выполнения цикла FOR /L, можно использовать в арифметических вычислениях. Рассмотрим командный файл my.bat следующего содержания:

@ECHO OFF
CLS
FOR /L %%f IN (1,1,5) DO CALL :2 %%f
GOTO :EOF
:2
SET /A M=10*%1
ECHO 10*%1=%M%

В третьей строке в цикле происходит вызов нового контекста файла my.bat с текущим значением переменной цикла %%f в качестве параметра командной строки, причем управление передается на метку :2 (см. описание CALL в разделе "Изменения в командах перехода"). В шестой строке переменная цикла умножается на десять, и результат записывается в переменную M. Таким образом, в результате выполнения этого файла выведется следующая информация:

10*1=10
10*2=20
10*3=30
10*4=40
10*5=50
Цикл FOR /F … IN … DO …

Самые мощные возможности (и одновременно самый запутанный синтаксис) имеет команда: FOR с ключом /F:

FOR /F ["ключи"] %%переменная IN (набор) 
 DO команда [параметры]

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

По умолчанию ключ /F выделяет из каждой строки файла первое слово, очищенное от окружающих его пробелов. Пустые строки в файле пропускаются. Необязательный параметр "ключи" служит для переопределения заданных по умолчанию правил обработки строк. Ключи представляют собой заключенную в кавычки строку, содержащую приведенные в табл. 3.3 ключевые слова:

Таблица 3.3. Ключи в команде FOR /F
КлючОписание
EOL=CОпределение символа комментариев в начале строки (допускается задание только одного символа)
SKIP=NЧисло пропускаемых при обработке строк в начале файла
DELIMS=XXXОпределение набора разделителей для замены заданных по умолчанию пробела и знака табуляции
TOKENS=X,Y,M-NОпределение номеров подстрок, выделяемых из каждой строки файла и передаваемых для выполнения в тело цикла

При использовании ключа TOKENS=X,Y,M-N создаются дополнительные переменные. Формат M-N представляет собой диапазон подстрок с номерами от M до N. Если последний символ в строке TOKENS= является звездочкой, то создается дополнительная переменная, значением которой будет весь текст, оставшийся в строке после обработки последней подстроки.

Разберем применение этой команды на примере пакетного файла parser.bat, который производит разбор файла myfile.txt:

@ECHO OFF
IF NOT EXIST myfile.txt GOTO :NoFile
FOR /F "EOL=; TOKENS=2,3* DELIMS=, " %%i IN 
  (myfile.txt) DO @ECHO %%i %%j %%k
GOTO :EOF
:NoFile
ECHO Не найден файл myfile.txt!

Здесь во второй строке производится проверка наличия файла myfile.txt; в случае отсутствия этого файла выводится предупреждающее сообщение. Команда FOR в третьей строке обрабатывает файл myfile.txt следующим образом:

Пропускаются все строки, которые начинаются с символа точки с запятой ( EOL=; ).

Вторая и третья подстроки из каждой строки передаются в тело цикла, причем подстроки разделяются пробелами (по умолчанию) и/или запятыми ( DELIMS=,).

В теле цикла переменная %%i используется для второй подстроки, %%j — для третьей, а %%k получает все оставшиеся подстроки после третьей.

В нашем примере переменная %%i явно описана в инструкции FOR, а переменные %%j и %%k описываются неявно с помощью ключа TOKENS=. Например, если в файле myfile.txt были записаны следующие три строки:

ААА ББББ ВВВВ,ГГГГГ ДДДД
ЕЕЕЕЕ,ЖЖЖЖ ЗЗЗЗ
;КККК ЛЛЛЛЛ МММММ

то в результате выполнения пакетного файла parser.bat на экран выведется следующее:

ББББ ВВВВ ГГГГГ ДДДД
ЖЖЖЖ ЗЗЗЗ

Замечание

Ключ TOKENS= позволяет извлечь из одной строки файла до 26 подстрок, поэтому запрещено использовать имена переменных, начинающиеся не с букв английского алфавита (a–z). Следует помнить, что имена переменных FOR являются глобальными, поэтому одновременно не может быть активно более 26 переменных.

Команда FOR /F также позволяет обработать отдельную строку. Для этого следует ввести нужную строку в кавычках вместо набора имен файлов в скобках. Строка будет обработана так, как будто она взята из файла. Например, файл следующего содержания:

@ECHO OFF
FOR /F "EOL=; TOKENS=2,3* DELIMS=, " %%i IN 
  ("ААА ББББ ВВВВ,ГГГГГ ДДДД") DO @ECHO %%i %%j %%k

при своем выполнении напечатает

ББББ ВВВВ ГГГГГ ДДДД

Вместо явного задания строки для разбора можно пользоваться переменными среды, например:

@ECHO OFF
SET M=ААА ББББ ВВВВ,ГГГГГ ДДДД
FOR /F "EOL=; TOKENS=2,3* DELIMS=, 
  " %%i IN ("%M%") DO @ECHO %%i %%j %%k

Наконец, команда FOR /F позволяет обработать строку вывода другой команды. Для этого следует вместо набора имен файлов в скобках ввести строку вызова команды в апострофах (не в кавычках!). Строка передается для выполнения интерпретатору команд cmd.exe, а вывод этой команды записывается в память и обрабатывается так, как будто строка вывода взята из файла. Например, следующий командный файл:

@ECHO OFF
CLS
ECHO Имена переменных среды:
ECHO.
FOR /F "DELIMS==" %%i IN ('SET') DO ECHO %%i

выведет перечень имен всех переменных среды, определенных в настоящее время в системе.

В цикле FOR допускается применение тех же синтаксических конструкций (операторов), что и для заменяемых параметров (табл. 3.4).

Таблица 3.4. Операторы для переменных команды FOR
ОператорыОписание
%~FiПеременная %i расширяется до полного имени файла
%~DiИз переменной %i выделяется только имя диска
%~PiИз переменной %i выделяется только путь к файлу
%~NiИз переменной %i выделяется только имя файла
%~XiИз переменной %i выделяется расширение имени файла
%~SiЗначение операторов N и X для переменной %i изменяется так, что они работают с кратким именем файла

Замечание

Если планируется использовать расширения подстановки значений в команде FOR, то следует внимательно подбирать имена переменных, чтобы они не пересекались с обозначениями формата.

Например, если мы находимся в каталоге C:\Program Files\Far и запустим командный файл следующего содержания:

@ECHO OFF
CLS
FOR %%i IN (*.txt) DO ECHO %%~Fi
то на экран выведутся полные имена всех файлов 
 с расширением txt:
C:\Program Files\Far\Contacts.txt
C:\Program Files\Far\FarFAQ.txt
C:\Program Files\Far\Far_Site.txt
C:\Program Files\Far\License.txt
C:\Program Files\Far\License.xUSSR.txt
C:\Program Files\Far\ReadMe.txt
C:\Program Files\Far\register.txt
C:\Program Files\Far\WhatsNew.txt
Циклы и связывание времени выполнения для переменных

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

SET a=
FOR %%i IN (Раз,Два,Три) DO SET a=%a%%%i
ECHO a=%a%

В результате его выполнения на экран будет выведена строка "a=Три", то есть фактически команда

FOR %%i IN (Раз,Два,Три) DO SET a=%a%%%i

равносильна команде

FOR %%i IN (Раз,Два,Три) DO SET a=%%i

Для исправления ситуации нужно, как и в случае с составными выражениями, вместо знаков процента ( % ) использовать восклицательные знаки и предварительно включить режим связывания времени выполнения командой SETLOCAL ENABLEDELAYEDEXPANSION. Таким образом, наш пример следует переписать следующим образом:

SETLOCAL ENABLEDELAYEDEXPANSION
SET a=
FOR %%i IN (Раз,Два,Три) DO SET a=!a!%%i
ECHO a=%a%

В этом случае на экран будет выведена строка "a=РазДваТри".

Лекция 4. Сервер сценариев WSH. Языки сценариев VBScript и JScript

Обсуждаются назначение и основные свойства сервера сценариев Windows Script Host (WSH). Описываются консольный и графический режимы работы сценариев WSH. Затрагиваются вопросы выбора языка для написания сценариев WSH

Сервер сценариев WSH. Языки сценариев VBScript и JScript

В двух предыдущих лекциях был рассмотрен язык командных файлов (язык командной оболочки), который в качестве инструмента для автоматизации работы поддерживается во всех версиях Windows. Однако с помощью командного интерпретатора cmd.exe трудно написать какую-либо сложную программу-сценарий (script): отсутствует полноценная интерактивность, нельзя напрямую работать с рабочим столом Windows и системным реестром и т. д.

Для исправления этой ситуации компанией Microsoft был разработан сервер сценариев Windows Script Host (WSH), с помощью которого можно выполнять сценарии, написанные, в принципе, на любом языке (при условии, что для этого языка установлен соответствующий модуль (scripting engine), поддерживающий технологию ActiveX Scripting). В качестве стандартных языков поддерживаются Visual Basic Script Edition (VBScript) и JScript.

Вообще говоря, принцип работы сценариев, поддерживаемых WSH, состоит в использовании объектов ActiveX, поэтому вначале мы очень кратко опишем возможности самой технологии ActiveX компании Microsoft.

Возможности технологии ActiveX

Напомним, что в Windows с самого начала для обеспечения обмена данными между приложениями была разработана технология связывания и внедрения объектов (Object Linking and Embedding, OLE). Вначале технология OLE использовалась для создания составных документов, а затем для решения более общей задачи — предоставления приложениями друг другу собственных функций (служб) и правильного использования этих функций. Технология, позволяющая одному приложению (клиенту автоматизации) вызывать функции другого приложения (сервера автоматизации) была названа OLE Automation. В основе OLE и OLE Automation лежит разработанная Microsoft базовая "компонентная" технология Component Object Model (COM). В общих словах, компонентное программное обеспечение — это способ разработки программ, при котором используются технологии создания программных модулей, подобные технологиям, применяемым для разработки аппаратных средств. Сложные элементные схемы собираются из стандартизированных микросхем, которые имеют четко определенные документированные функции. Разработчик может эффективно пользоваться такими микросхемами, не задумываясь об их внутренней структуре. В программных компонентах, написанных на каком-либо языке программирования, детали реализации используемых алгоритмов также скрыты внутри компонента (объекта), а на поверхности находятся общедоступные интерфейсы, которыми могут пользоваться и другие приложения, написанные на том же или другом языке.

В настоящее время термин OLE используется только по историческим причинам. Вместо него Microsoft с 1996 года использует новый термин — ActiveX, первоначально обозначавший WWW (World Wide Web) компоненты (объекты), созданные на базе технологии COM.

Технология ActiveX длительное время являлась ключевой в продуктах Microsoft. Наиболее полное воплощение она нашла в программах Microsoft Office, Internet Explorer, Internet Information Service (IIS). В эти продукты для управления соответствующими объектами автоматизации были встроены интерпретаторы специальных языков сценариев: VBScript (используется в Microsoft Office, Internet Explorer, IIS) и JScript (используется в Internet Explorer, IIS). Однако непосредственно в операционной системе, вне этих продуктов, выполнять сценарии, написанные на VBScript или JScript, было нельзя.

Сервер сценариев WSH является мощным инструментом, предоставляющим единый интерфейс (объектную модель) для специализированных языков (VBScript, JScript, PerlScript, REXX, TCL, Python и т. п.), которые, в свою очередь, позволяют использовать любые внешние объекты ActiveX. С помощью WSH сценарии могут быть выполнены непосредственно в операционной системе Windows, без встраивания в HTML-страницы.

Назначение и основные свойства WSH

WSH предъявляет минимальные требования к объему оперативной памяти, и является очень удобным инструментом для автоматизации повседневных задач пользователей и администраторов операционной системы Windows. Используя сценарии WSH, можно непосредственно работать с файловой системой компьютера, а также управлять работой других приложений (серверов автоматизации). При этом возможности сценариев ограничены только средствами, которые предоставляют доступные серверы автоматизации.

Перечислим только наиболее очевидные задачи, для автоматизации которых прекрасно подходят сценарии WSH.

Создание и запуск простейших сценариев WSH

Простейший WSH-сценарий, написанный на языке JScript или VBScript — это обычный текстовый файл с расширением js или vbs соответственно, создать его можно в любом текстовом редакторе, способном сохранять документы в формате "Только текст".

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

В качестве первого примера создадим JScript-сценарий, выводящий на экран диалоговое окно с надписью "Привет!". Для этого достаточно c помощью, например, стандартного Блокнота Windows (notepad.exe) создать файл First.js, содержащий всего одну строку:

WScript.Echo("Привет!");

Тот же самый сценарий на языке VBScript, естественно, отличается синтаксисом и выглядит следующим образом:

WScript.Echo "Привет!"

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

/*******************************************************************/
/* Имя: First.js                                                   */
/* Язык: JScript                                                   */
/* Описание: Вывод на экран приветствия                            */
/*******************************************************************/

На языке VBScript то же самое выглядит следующим образом:

'*******************************************************************
' Имя: First.vbs
' Язык: VBScript
' Описание: Вывод на экран приветствия
'*******************************************************************

Для запуска сценариев WSH существует несколько способов.

Запуск сценария из командной строки в консольном режиме

Можно выполнить сценарий из командной строки с помощью консольной версии WSH cscript.exe. Например, чтобы запустить сценарий, записанный в файле C:\Script\First.js, нужно загрузить командное окно и выполнить в нем команду

cscript C:\Script\First.js

В результате выполнения этого сценария в командное окно выведется строка "Привет!" (рис. 4.1)

Результат выполнения First.js в консольном режиме (cscript.exe)


увеличить изображение

Рис. 4.1.  Результат выполнения First.js в консольном режиме (cscript.exe)

Запуск сценария из командной строки в графическом режиме

Сценарий можно выполнить из командной строки с помощью (оконной) графической версии WSH wscript.exe. Для нашего примера в этом случае нужно выполнить команду

wscript C:\Script\First.js

Тогда в результате выполнения сценария на экране появится нужное нам диалоговое окно (рис. 4.2).

Результат выполнения First.js в графическом режиме (wscript.exe)


увеличить изображение

Рис. 4.2.  Результат выполнения First.js в графическом режиме (wscript.exe)

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

Запуск сценария с помощью меню Пуск

Для запуска сценария с помощью пункта Выполнить (Run) меню Пуск (Start), достаточно написать полное имя этого сценария в поле Открыть (Open) и нажать кнопку Ok. В этом случае по умолчанию сценарий будет выполнен с помощью wscript.exe, т. е. вывод информации будет вестись в графическое диалоговое окно.

Запуск сценария с помощью Проводника Windows (Windows Explorer)

Самым простым является запуск сценария в окнах Проводника Windows или на рабочем столе — достаточно просто выполнить двойной щелчок мышью на имени файла со сценарием или на его значке (аналогично любому другому исполняемому файлу). При этом, как и в случае запуска с помощью меню Пуск (Start), сценарий по умолчанию выполняется с помощью wscript.exe.

Установка и изменение свойств сценариев

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

Если сценарий запускается в консольном режиме, то его исполнение контролируется с помощью параметров командной строки для cscript.exe (см. табл. 4.1), которые включают или отключают различные опции WSH (все эти параметры начинаются с символов "//").

Таблица 4.1. Параметры командной строки для cscript.exe
ПараметрОписание
//IВыключает пакетный режим (по умолчанию). При этом на экран будут выводиться все сообщения об ошибках в сценарии
//BВключает пакетный режим. При этом на экран не будут выводиться никакие сообщения
//T:nnЗадает тайм-аут в секундах, т. е. сценарий будет выполняться nn секунд, после чего процесс прервется. По умолчанию время выполнения не ограничено
//LogoВыводит (по умолчанию) перед выполнением сценария информацию о версии и разработчике WSH
//NologoПодавляет вывод информации о версии и разработчике WSH
//H:CScript или //H:WscriptДелает cscript.exe или wscript.exe приложением для запуска сценариев по умолчанию. Если эти параметры не указаны, то по умолчанию подразумевается wscript.exe
//SСохраняет установки командной строки для текущего пользователя
//?Выводит встроенную подсказку для параметров командной строки
//E:engineВыполняет сценарий с помощью модуля, заданного параметром engine
//DВключает отладчик
//XВыполняет программу в отладчике
//Job:<JobID>Запускает задание с индексом JobID из многозадачного WS-файла (структура WS-файлов будет описана ниже)
//UПозволяет использовать при перенаправлении ввода-вывода с консоли кодировку Unicode

Например, команда

cscript //Nologo C:\Script\First.js

запустит сценарий First.js без информации о версии WSH.

Сценарий можно запускать с параметрами командной строки, которые указываются после имени этого сценария (процедура обработки таких параметров будет описана ниже, при рассмотрении объектов WshArguments, WshNamed и WshUnnamed ). Например, команда

cscript //B C:\Script\First.js /a /b

запустит сценарий First.js в пакетном режиме, при этом /a и /b будут являться параметрами этого сценария, а //B — параметром приложения cscript.exe.

Если сценарий запускается в графическом режиме (с помощью wscript.exe), то свойства сценария можно устанавливать с помощью вкладки Сценарий (Script) диалогового окна, задающего свойства файла в Windows (рис. 4.3).

Установка свойств сценария First.js


Рис. 4.3.  Установка свойств сценария First.js

После задания свойств сценария автоматически создается файл с именем этого сценария и расширением wsh, который имеет структуру наподобие ini-файла, например:

[ScriptFile]
Path=C:\Script\First.js
[Options]
Timeout=0
DisplayLogo=1

Если дважды щелкнуть в Проводнике Windows по wsh-файлу или запустить такой файл из командной строки, то соответствующий сервер сценариев (wscript.exe или cscript.exe) запустит сценарий, которому соответствует wsh-файл, с заданными в секции Options параметрами.

При запуске сценариев с помощью wscript.exe для задания параметров командной строки сценария можно использовать технологию drag-and-drop — если выделить в Проводнике Windows несколько файлов и перетащить их на ярлык сценария, то этот сценарий запустится, а имена выделенных файлов передадутся ему в качестве параметров.

Языки VBScript и JScript для сценариев WSH

Как уже отмечалось выше, в принципе сценарии WSH можно писать на любом языке, поддерживающем технологию ActiveX Scripting. Однако для всех таких языков, кроме VBScript и JScript, в системе придется дополнительно устанавливать те или иные модули (библиотеки) поддержки. Поэтому чаще всего при работе с WSH пользуются именно языками VBScript или JScript – сценарии на этих языках гарантированно работают на любой машине с операционной системой Windows.

По синтаксису и стилю программирования эти два языка сильно отличаются друг от друга. Язык JScript — это разработанный Microsoft интерпретируемый объектно-ориентированный язык сценариев, который первоначально предназначался для создания динамических HTML-страниц. Отметим, что JScript не является урезанной версией какого-либо другого языка программирования, хотя по синтаксису он похож на языки Java и C. Язык VBScript (Visual Basic Script Edition) – это облегченная версия языка Microsoft Visual Basic, поэтому для тех, кто программировал на Visual Basic или VBA (Visual Basic for Application) язык VBScript окажется очень знакомым.

Какой именно из языков использовать – в большей степени дело вкуса и привычки. Если вы писали на C или Java, то, скорее всего, остановитесь на JScript; если вы программируете на Visual Basic или VBA (Visual Basic for Application), то очень знакомым вам окажется язык VBScript.

Отметим также, что при выборе языка для написания сценария, обращающегося к внешним объектам (а это делается практически в каждом сценарии Windows), в пользу VBScript можно привести несколько дополнительных аргументов.

Во-первых, VBScript позволяет напрямую в цикле For Each … Next перебирать элементы коллекций (такие коллекции часто являются свойствами внешних объектов), а в JScript для этого приходится использовать вспомогательный объект Enumerator и цикл for с условием завершения и оператором итерации. Рассмотрим следующий пример. Предположим, что переменная Folder является объектом, соответствующим корневому каталогу диска C:, т.е. Folder представляет собой коллекцию, содержащую объекты-файлы, находящиеся в корневом каталоге. Тогда перебор всех этих файлов в VBScript организуется следующим образом:

'Создаем коллекцию Files всех файлов в корневом каталоге диска C:
Set Files = Folder.Files
'Перебираем все элементы коллекции Files
For Each File In Files
  'Выделяем имя файла для текущего элемента File коллекции
  s = s & File.Name & vbCrLf
Next

Аналогичный код на JScript выглядит так:

//Создаем коллекцию файлов
Files=new Enumerator(Folder.Files);
//Цикл по всем файлам
for (; !Files.atEnd(); Files.moveNext()) 
  //Добавляем строку с именем файла
  s+=Files.item().Name+"\n";
//Выводим полученные строки на экран

Во-вторых, VBScript позволяет напрямую вызывать методы объектов WMI (технология WMI будет подробно рассмотрена в следующих лекциях), в то время как в JScript эти методы приходится вызывать с помощью специального объекта SWbemObject, а также объектов InParam (входящие параметры для вызова метода) и OutParam (параметры, формируемые после выполнения метода).

Наконец, подавляющее большинство примеров сценариев, которые можно найти в документации Microsoft или сети Интернет, написаны на VBScript, их можно использовать в своих разработках без изменений, не тратя время на перевод кода на другой язык.

Подробное рассмотрение синтаксиса языков VBScript и JScript выходит за рамки данного курса; ниже в примерах сценариев мы будем преимущественно использовать VBScript.

Лекция 5. Собственная объектная модель WSH

Рассматриваются основные объекты, поддерживаемые WSH (WScript, WshShell, WshEnvironment, WshSpecialFolders, WshArguments). Даются примеры сценариев для работы со стандартными объектами WSH

Собственная объектная модель WSH

Перейдем к описанию собственной объектной модели Windows Script Host. С помощью внутренних объектов WSH из сценариев можно выполнять следующие основные задачи:

В WSH версии 5.6 (стандартная версия в Windows XP) входят перечисленные ниже объекты:

Кроме этого, имеется объект FileSystemObject, обеспечивающий доступ к файловой системе компьютера (этот объект будет подробно рассмотрен в следующей лекции).

Рассмотрим более подробно несколько объектов WSH, которые часто используются в сценариях.

Объект WScript

Свойства объекта WScript позволяют получить полный путь к использующемуся серверу сценариев (wscript.exe или cscript.exe), параметры командной строки, с которыми запущен сценарий, режим его работы (интерактивный или пакетный). Кроме этого, с помощью свойств объекта WScript можно выводить информацию в стандартный выходной поток и читать данные из стандартного входного потока. Также WScript предоставляет методы для работы внутри сценария с объектами автоматизации и вывода информации на экран (в текстовом режиме) или в окно Windows.

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

Свойства объекта WScript представлены в табл. 5.1.

Таблица 5.1. Свойства объекта WScript
СвойствоОписание
ApplicationПредоставляет интерфейс Idispatch для объекта WScript
ArgumentsСодержит указатель на коллекцию WshArguments, содержащую параметры командной строки для исполняемого сценария
FullNameСодержит полный путь к исполняемому файлу сервера сценариев (в Windows XP обычно это C:\WINDOWS\SYSTEM32\CSCRIPT.EXE или C:\WINDOWS\SYSTEM32\WSCRIPT.EXE)
NameСодержит название объекта Wscript (Windows Script Host)
PathСодержит путь к каталогу, в котором находится cscript.exe или wscript.exe (в Windows XP обычно это C:\WINDOWS\SYSTEM32)
ScriptFullNameСодержит полный путь к запущенному сценарию
ScriptNameСодержит имя запущенного сценария
StdErrПозволяет запущенному сценарию записывать сообщения в стандартный поток для ошибок
StdInПозволяет запущенному сценарию читать информацию из стандартного входного потока
StdOutПозволяет запущенному сценарию записывать информацию в стандартный выходной поток
VersionСодержит версию WSH

Опишем более подробно некоторые свойства объекта WScript.

Свойство Arguments

В следующем примере (листинг 5.1) с помощью цикла For Each … Next на экран выводятся все параметры командной строки, с которыми был запущен сценарий.

'********************************************************************
' Имя: Args.vbs                                                   
' Язык: VBScript                                                    
' Описание: Работа с аргументами запущенного сценария              
'********************************************************************
Option Explicit

Dim s,objArgs,Arg 
Set objArgs = WScript.Arguments  ' Создаем объект WshArguments
For Each Arg In objArgs
  s=s & Arg ' Формируем строки со значениями аргументов
Next

WScript.Echo s   ' Выводим сформированные строки
'*************  Конец *********************************************
Листинг 5.1. Вывод всех параметров командной строки сценария (VBScript) (html, txt)
Свойства StdErr, StdIn, StdOut

Доступ к стандартным входным и выходным потокам с помощью свойств StdIn, StdOut и StdErr можно получить только в том случае, если сценарий запускался в консольном режиме с помощью cscript.exe. Если сценарий был запущен с помощью wscript.exe, то при попытке обратиться к этим свойствам возникнет ошибка "Invalid Handle".

Работать с потоками StdOut и StdErr можно с помощью методов Write, WriteLine, WriteBlankLines, а с потоком StdIn — с помощью методов Read, ReadLine, ReadAll, Skip, SkipLine. Эти методы кратко описаны в табл. 5.2.

Таблица 5.2. Методы для работы с потоками
МетодОписание
Read(n)Считывает из потока StdIn заданное параметром n число символов и возвращает полученную строку
ReadAll()Читает символы из потока StdIn до тех пор, пока не встретится символ конца файла ASCII 26 (<Ctrl>+<Z>), и возвращает полученную строку
ReadLine()Возвращает строку, считанную из потока StdIn
Skip(n)Пропускает при чтении из потока StdIn заданное параметром n число символов
SkipLine()Пропускает целую строку при чтении из потока StdIn
Write(string)Записывает в поток StdOut или StdErr строку string (без символа конца строки)
WriteBlankLines(n)Записывает в поток StdOut или StdErr заданное параметром n число пустых строк
WriteLine(string)Записывает в поток StdOut или StdErr строку string (вместе с символом конца строки)

Напомним, что операционная система Windows поддерживает механизм конвейеризации (символ "|" в командной строке). Этот механизм делает возможным передачу данных от одной программы к другой. Таким образом, используя стандартные входные и выходные потоки, можно из сценария обрабатывать строки вывода другого приложения или перенаправлять выводимые сценарием данные на вход программ-фильтров ( FIND или SORT ). Например, следующая команда будет сортировать строки вывода сценария example.js и выводить их в файл sort.txt:

cscript //Nologo example.js | sort > sort.txt

Опция //Nologo здесь нужна для того, чтобы в файл sort.txt не попадали строки с информацией о разработчике и номере версии WSH.

Кроме этого, с помощью методов, работающих с входным потоком StdIn, можно организовывать диалог с пользователем, то есть создавать интерактивные сценарии. Соответствующий пример приведен в листинге 5.2.

'*******************************************************************
'* Имя: Interact.vbs                                               
'* Язык: VBScript                                                  
'* Описание: Ввод/вывод строк в консольном режиме                  
'*******************************************************************
Dim  s
' Выводим строку на экран
WScript.StdOut.Write "Введите число: "
' Считываем строку
s = WScript.StdIn.ReadLine
' Выводим строку на экран
WScript.StdOut.WriteLine "Вы ввели число " & s
'*************  Конец *********************************************
Листинг 5.2. Ввод/вывод строк в символьном режиме (html, txt)
Методы объекта WScript

Объект WScript имеет несколько методов, которые описаны в табл. 5.3.

Таблица 5.3. Методы объекта WScript
МетодОписание
CreateObject(strProgID [, strPrefix])Создает объект, заданный параметром strProgID
ConnectObject(strObject, strPrefix)Устанавливает соединение с объектом strObject, позволяющее писать функции-обработчики его событий (имена этих функций должны начинаться с префикса strPrefix )
DisconnectObject(obj)Отсоединяет объект obj, связь с которым была предварительно установлена в сценарии
Echo([Arg1] [, Arg2] [,…])Выводит текстовую информацию на консоль или в диалоговое окно
GetObject(strPathname [, strProgID], [strPrefix])Активизирует объект автоматизации, определяемый заданным файлом (параметр strPathName ) или объект, заданный параметром strProgID
Quit([intErrorCode])Прерывает выполнение сценария с заданным параметром intErrorCode кодом выхода. Если параметр intErrorCode не задан, то объект WScript установит код выхода равным нулю
Sleep(intTime)Приостанавливает выполнения сценария (переводит его в неактивное состояние) на заданное параметром intTime число миллисекунд

Приведем дополнительные пояснения и примеры использования для методов, приведенных в табл. 5.3.

Метод CreateObject

Строковый параметр strProgID, указываемый в методе CreateObject, называется программным идентификатором объекта (Programmic Identifier, ProgID).

Если указан необязательный параметр strPrefix, то после создания объекта в сценарии можно обрабатывать события, возникающие в этом объекте (естественно, если объект предоставляет интерфейсы для связи с этими событиями). Когда объект сообщает о возникновении определенного события, сервер сценариев вызывает функцию, имя которой состоит из префикса strPrefix и имени этого события. Например, если в качестве strPrefix указано "MYOBJ_", а объект сообщает о возникновении события "OnBegin," то будет запущена функция "MYOBJ_OnBegin", которая должна быть описана в сценарии.

В следующем примере метод CreateObject используется для создания объекта WshNetwork:

var WshNetwork = WScript.CreateObject("WScript.Network");

Отметим, что объекты автоматизации из сценариев можно создавать и без помощи WSH. В JScript для этого используется объект ActiveXObject, например:

var WshNetwork = new ActiveXObject("WScript.Network");

В VBScript для создания объектов может использоваться специальная функция CreateObject, например:

Set WshNetwork = CreateObject("WScript.Network")

Однако организовать в сценарии обработку событий создаваемого объекта можно только при использовании метода WScript.CreateObject.

Метод ConnectObject

Объект, соединение с которым осуществляется с помощью метода ConnectObject, должен предоставлять интерфейс к своим событиям.

В следующем примере в переменной MyObject создается абстрактный объект "SomeObject", затем из сценария вызывается метод SomeMetod этого объекта. После этого устанавливается связь с переменной MyObject и задается префикс "MyEvent" для процедур обработки события этого объекта. Если в объекте возникнет событие с именем "Event", то будет вызвана функция MyEvent_Event. Метод DisconnectObject объекта WScript производит отсоединение объекта MyObject.

var MyObject = WScript.CreateObject("SomeObject");
MyObject.SomeMethod();
WScript.ConnectObject(MyObject,"MyEvent");

function MyEvent_Event(strName){
  WScript.Echo(strName);
  }
WScript.DisconnectObject(MyObject);
Метод Echo

Параметры Arg1, Arg2, … метода Echo задают аргументы для вывода. Если сценарий был запущен с помощью wscript.exe, то метод Echo направляет вывод в диалоговое окно, если же для выполнения сценария применяется cscript.exe, то вывод будет направлен на экран (консоль). Каждый из аргументов при выводе будет разделен пробелом. В случае использования cscript.exe вывод всех аргументов будет завершен символом новой строки. Если в методе Echo не задан ни один аргумент, то будет напечатана пустая строка.

Например, после выполнения сценария EchoExample.vbs (листинг 5.3) с помощью cscript.exe на экран будут выведены пустая строка, три числа и строка текста.

'*******************************************************************
'* Имя: EchoExample.vbs                                            
'* Язык: VBScript                                                   
'* Описание: Использование метода WScript.Echo                     
'*******************************************************************
WScript.Echo            'Выводим пустую строку
WScript.Echo 1,2,3      'Выводим числа
WScript.Echo "Привет!"  'Выводим строку
'*************  Конец *********************************************
Листинг 5.3. Использование метода WScript.Echo (html, txt)
Метод Sleep

В следующем примере сценарий переводится в неактивное состояние на 5 секунд:

'*******************************************************************
'* Имя: SleepExample.vbs                                            
'* Язык: VBScript                                                   
'* Описание: Использование метода WScript.Sleep                     
'*******************************************************************
WScript.Echo "Сценарий запущен, отдыхаем…"
WScript.Sleep 5000
WScript.Echo "Выполнение сценария завершено"
'*************  Конец *********************************************
Листинг 5.4. Использование метода WScript.Sleep (html, txt)

Метод Sleep необходимо применять при асинхронной работе сценария и какой-либо другой задачи, например, при имитации нажатий клавиш в активном окне с помощью метода WshShell.SendKeys.

Объект WshShell

С помощью объекта WshShell можно запускать новый процесс, создавать ярлыки, работать с системным реестром, получать доступ к переменным среды и специальным папкам Windows. Создается этот объект следующим образом:

var WshShell=WScript.CreateObject("WScript.Shell");

Объект WshShell имеет три свойства, которые приведены в табл. 5.4.

Таблица 5.4. Свойства объекта WshShell
СвойствоОписание
CurrentDirectoryЗдесь хранится полный путь к текущему каталогу (к каталогу, из которого был запущен сценарий)
EnvironmentСодержит объект WshEnvironment, который обеспечивает доступ к переменным среды операционной системы для Windows NT/2000/XP или к переменным среды текущего командного окна для Windows 9x
SpecialFoldersСодержит объект WshSpecialFolders для доступа к специальным папкам Windows (рабочий стол, меню Пуск (Start) и т. д.)

Опишем теперь методы, имеющиеся у объекта WshShell (табл. 5.5).

Таблица 5.5. Методы объекта WshShell
МетодОписание
AppActivate(title)Активизирует заданное параметром title окно приложения. Строка title задает название окна (например, "calc" или "notepad" ) или идентификатор процесса ( Process ID, PID )
CreateShortcut(strPathname)Создает объект WshShortcut для связи с ярлыком Windows (расширение lnk) или объект WshUrlShortcut для связи с сетевым ярлыком (расширение url). Параметр strPathname задает полный путь к создаваемому или изменяемому ярлыку
Environment(strType)Возвращает объект WshEnvironment, содержащий переменные среды заданного вида
Exec(strCommand)Создает новый дочерний процесс, который запускает консольное приложение, заданное параметром strCommand. В результате возвращается объект WshScriptExec, позволяющий контролировать ход выполнения запущенного приложения и обеспечивающий доступ к потокам StdIn, StdOut и StdErr этого приложения
ExpandEnvironmentStrings(strString)Возвращает значение переменной среды текущего командного окна, заданной строкой strString (имя переменной должно быть окружено знаками "%" )
LogEvent(intType, strMessage [,strTarget])Протоколирует события в журнале Windows NT/2000/XP или в файле WSH.log. Целочисленный параметр intType определяет тип сообщения, строка strMessage — текст сообщения. Параметр strTarget может задаваться только в Windows NT/2000/XP, он определяет название системы, в которой протоколируются события (по умолчанию это локальная система). Метод LogEvent возвращает true, если событие записано успешно и false в противном случае
Popup(strText,[nSecToWait], [strTitle], [nType])Выводит на экран информационное окно с сообщением, заданным параметром strText. Параметр nSecToWait задает количество секунд, по истечении которых окно будет автоматически закрыто, параметр strTitle определяет заголовок окна, параметр nType указывает тип кнопок и значка для окна
RegDelete(strName)Удаляет из системного реестра заданный параметр или раздел целиком
RegRead(strName)Возвращает значение параметра реестра или значение по умолчанию для раздела реестра
RegWrite(strName, anyValue [,strType])Записывает в реестр значение заданного параметра или значение по умолчанию для раздела
Run(strCommand, [intWindowStyle], [bWaitOnReturn])Создает новый независимый процесс, который запускает приложение, заданное параметром strCommand
SendKeys(string)Посылает одно или несколько нажатий клавиш в активное окно (эффект тот же, как если бы вы нажимали эти клавиши на клавиатуре)
SpecialFolders(strSpecFolder)Возвращает строку, содержащую путь к специальной папке Windows, заданной параметром strSpecFolder

Рассмотрим более подробно некоторые методы, приведенные в табл. 5.5.

Метод CreateShortcut

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

Приведем пример сценария, в котором создаются два ярлыка — на сам выполняемый сценарий (объект oShellLink ) и на сетевой ресурс ( oUrlLink ).

'*****************************************************************
'* Имя: MakeShortcuts.vbs                                        
'* Язык: VBScript                                                 
'* Описание: Создание ярлыков из сценария                        
'*****************************************************************
Dim WshShell,oShellLink,oUrlLink
' Создаем объект WshShell
Set WshShell=WScript.CreateObject("WScript.Shell")
' Создаем ярлык на файл
Set oShellLink=WshShell.CreateShortcut("Current Script.lnk")
' Устанавливаем путь к файлу
oShellLink.TargetPath=WScript.ScriptFullName
' Сохраняем ярлык
oShellLink.Save

' Создаем ярлык на сетевой ресурс
Set oUrlLink = WshShell.CreateShortcut("Microsoft Web Site.URL")
' Устанавливаем URL
oUrlLink.TargetPath = "http://www.microsoft.com"
' Сохраняем ярлык
oUrlLink.Save
'*************  Конец *********************************************
Листинг 5.5. Создание ярлыков из сценария (VBScript) (html, txt)
Метод Environment

Параметр strType задает вид переменных среды, которые будут записаны в коллекции WshEnvironment ; возможными значениями этого параметра являются "System" (переменные среды операционной системы), "User" (переменные среды пользователя), "Volatile" (временные переменные) или "Process" (переменные среды текущего командного окна).

В следующем примере (листинг 5.6) мы распечатываем число процессоров, имеющихся в компьютере с операционной системой Windows XP (переменная NUMBER_OF_PROCESSORS ), и тип операционной системы.

'*****************************************************************
'* Имя: ShowEnvir.vbs                                             
'* Язык: VBScript                                                 
'* Описание: Получение значений некоторых переменных среды       
'*****************************************************************
Dim WshShell,WshSysEnv
' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
' Создание коллекции WshEnvironment
Set WshSysEnv = WshShell.Environment("SYSTEM")
WScript.Echo WshSysEnv("OS")
WScript.Echo WshShell.Environment.Item("NUMBER_OF_PROCESSORS")
'*************  Конец *********************************************
Листинг 5.6. Получение значений переменных среды (VBScript) (html, txt)
Метод Run

Параметр intWindowStyle устанавливает вид окна для запускаемого приложения (табл. 5.6).

Таблица 5.6. Типы окна (intWindowStyle)
ПараметрКонстанта Visual BasicОписание
0vbHideПрячет текущее окно и активизирует другое окно (показывает его и передает ему фокус)
1vbNormalFocusАктивизирует и отображает окно. Если окно было минимизировано или максимизировано, система восстановит его первоначальное положение и размер. Этот флаг должен указываться сценарием во время первого отображения окна
2vbMinimizedFocusАктивизирует окно и отображает его в минимизированном (свернутом) виде
3vbMaximizedFocusАктивизирует окно и отображает его в максимизированном (развернутом) виде
4vbNormalNoFocusОтображает окно в том виде, в котором оно находилось последний раз. Активное окно при этом остается активным
5Активизирует окно и отображает его в текущем состоянии
6vbMinimizedNoFocusМинимизирует заданное окно и активизирует следующее (в Z-порядке) окно
7Отображает окно в свернутом виде. Активное окно при этом остается активным
8Отображает окно в его текущем состоянии. Активное окно при этом остается активным
9Активизирует и отображает окно. Если окно было минимизировано или максимизировано, система восстановит его первоначальное положение и размер. Этот флаг должен указываться, если производится восстановление свернутого окна (его нельзя использовать в методе Run )
10Устанавливает режим отображения, опирающийся на режим программы, которая запускает приложение

Необязательный параметр bWaitOnReturn является логической переменной, дающей указание ожидать завершения запущенного процесса. Если этот параметр не указан или установлен в false, то после запуска из сценария нового процесса управление сразу же возвращается обратно в сценарий (не дожидаясь завершения запущенного процесса). Если же bWaitOnReturn установлен в true, то сценарий возобновит работу только после завершения вызванного процесса.

При этом если параметр bWaitOnReturn равен true, то метод Run возвращает код выхода вызванного приложения. Если же bWaitOnReturn равен false или не задан, то метод Run всегда возвращает ноль.

Следующий сценарий (листинг 5.7) печатает код выхода вызванного приложения (Блокнот).

'********************************************************************
'* Имя: RetCode.vbs                                                  
'* Язык: VBScript                                                    
'* Описание: Вывод кода выхода запущенного приложения               
'********************************************************************
' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
' Запускаем Блокнот и ожидаем завершения его работы
Return = WshShell.Run("notepad " + WScript.ScriptFullName, 1, true)
' Печатаем код возврата
WScript.Echo "Код возврата:", Return
'*************  Конец ***********************************************
Листинг 5.7. Вывод кода выхода запущенного приложения (html, txt)
Метод SendKeys

Каждая клавиша задается одним или несколькими символами. Например, Для того чтобы задать нажатие друг за другом букв А, Б и В нужно указать в качестве параметра для SendKeys строку "АБВ": string="АБВ".

Несколько символов имеют в методе SendKeys специальное значение: +, ^, %, ~, (, ). Для того чтобы задать один из этих символов, их нужно заключить в фигурные скобки ( {} ). Например, для задания знака плюс используется {+}. Квадратные скобки ( [] ) хотя и не имеют в методе SendKeys специального смысла, их также нужно заключать в фигурные скобки. Кроме этого, для задания самих фигурных скобок следует использовать следующие конструкции: {{} (левая скобка) и {}} (правая скобка).

Для задания неотображаемых символов, таких как <Enter> или <Tab>, и специальных клавиш в методе SendKeys используются коды, представленные в табл.5.7.

Таблица 5.7. Коды специальных клавишей для SendKeys
Названия клавишиКодНазвания клавишиКод
<Backspace>{BACKSPACE}, {BS} или {BKSP}< >{RIGHT}
<Break>{BREAK}<F1>{F1}
<Caps Lock>{CAPSLOCK}<F2>{F2}
<Del> или <Delete>{DELETE} или {DEL}<F3>{F3}
<End>{END}<F4>{F4}
<Enter>{ENTER} или ~<F5>{F5}
<Esc>{ESC}<F6>{F6}
<Home>{HOME}<F7>{F7}
<Ins> или <Insert>{INSERT} или {INS}<F8>{F8}
<Num Lock>{NUMLOCK}<F9>{F9}
<Page Down>{PGDN}<F10>{F10}
<Page Up>{PGUP}<F11>{F11}
<Print Screen>{PRTSC}<F12>{F12}
<Scroll Lock>{SCROLLLOCK}<F13>{F13}
<Tab>{TAB}<F14>{F14}
< >{UP}<F15>{F15}
< >{LEFT}<F16>{F16}
< >{DOWN}

Для задания комбинаций клавиш с <Shift>, <Ctrl> или <Alt>, перед соответствующей клавишей нужно поставить один или несколько кодов из табл. 5.8:

Таблица 5.8. Коды клавиш <Shift>, <Ctrl> и <Alt>
КлавишаКод
<Shift>+
<Ctrl>^
<Alt>%

Для того чтобы задать комбинацию клавиш, которую нужно набирать, удерживая нажатыми клавиши <Shift>, <Ctrl> или <Alt>, нужно заключить коды этих клавиш в скобки. Например, если требуется сымитировать нажатие клавиш G и S при нажатой клавише <Shift>, следует использовать последовательность "+(GS)". Для того же, чтобы задать одновременное нажатие клавиш <Shift>+<G>, а затем <S> (уже без <Shift>), используется "+GS".

В методе SendKeys можно задать несколько нажатий подряд одной и той же клавиши. Для этого необходимо в фигурных скобках указать код нужной клавиши, а через пробел — число нажатий. Например, {LEFT 42} означает нажатие клавиши <?> 42 раза подряд; {h 10} означает нажатие клавиши h 10 раз подряд.

В качестве примера использования методов SendKeys и AppActivate приведен сценарий RunCalc.vbs (листинг 5.8), который запускает стандартный калькулятор Windows и выполняет в нем несколько простых арифметических действий.

'*****************************************************************
'* Имя: RunCalc.vbs                                               
'* Язык: VBScript                                                 
'* Описание: Активизация приложения с помощью имени окна         
'*****************************************************************
Dim WshShell
' Создаем объект WshShell
Set WshShell=WScript.CreateObject("WScript.Shell")
' Запускаем Калькулятор
WshShell.Run "calc"
' Приостанавливаем сценарий на 1 секунду
WScript.Sleep 1000
' Активизируем Калькулятор
WshShell.AppActivate "Calculator"
' Приостановка сценария на 0,1 секунды
WScript.Sleep(100)
' Посылаем нажатия клавиш в Калькулятор
WshShell.SendKeys "1{+}"
WScript.Sleep 500
WshShell.SendKeys "2"
WScript.Sleep 500
WshShell.SendKeys "~"
WScript.Sleep 2500
'*************  Конец *********************************************
Листинг 5.8. Стандартный калькулятор Windows (html, txt)

Объекты-коллекции

В WSH входят объекты, с помощью которых можно получить доступ к коллекциям, содержащим следующие элементы:

Объект WshArguments

Объект WshArguments содержит коллекцию всех параметров командной строки запущенного сценария или ярлыка Windows. Этот объект можно создать только с помощью свойства Arguments объектов WScript и WshShortcut.

С помощью объекта WshArguments можно также выделять и отдельно обрабатывать аргументы сценария, у которых имеются имена (например, /Name:Andrey ) и безымянные аргументы. Ясно, что использование именных параметров более удобно, так как в этом случае нет необходимости запоминать, в каком порядке должны быть записаны параметры при запуске того или иного сценария.

Для доступа к именным и безымянным аргументам используются соответственно два специальных свойства объекта WshArguments: Named и Unnamed. Свойство Named содержит ссылку на коллекцию WshNamed, свойство Unnamed — на коллекцию WshUnnamed.

Таким образом, обрабатывать параметры командной строки запущенного сценария можно тремя способами:

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

'********************************************************************
' Имя: Args.vbs
' Язык: VBScript
' Описание: Работа с аргументами запущенного сценария
'********************************************************************
Option Explicit

Dim i,Arg,objArgs,s,objNamedArgs,objUnnamedArgs  ' Объявляем переменные

Set objArgs = WScript.Arguments  ' Создаем объект WshArguments
' Определяем общее количество аргументов
s="Всего аргументов: " & objArgs.Count() & vbCrLf
For Each Arg In objArgs
  s=s & Arg & vbCrLf  ' Формируем строки со значениями аргументов
Next

Set objUnnamedArgs=objArgs.Unnamed  ' Создаем объект WshUnnamed
' Определяем количество безымянных аргументов
s=s & vbCrLf & "Безымянных аргументов: " & objUnnamedArgs.length & vbCrLf
For Each Arg In objUnnamedArgs
  ' Формируем строки со значениями безымянных аргументов
  s=s & Arg & vbCrLf
Next

Set objNamedArgs=objArgs.Named  ' Создаем объект WshNamed
' Определяем количество именных аргументов
s=s & vbCrLf & "Именных аргументов: " & objNamedArgs.Length & vbCrLf
' Проверяем, существует ли аргумент /Имя:
If objNamedArgs.Exists("Имя") Then
  s=s & objNamedArgs("Имя") & vbCrLf
End If
' Проверяем, существует ли аргумент /Comp:
If objNamedArgs.Exists("Comp") Then
  s=s & objNamedArgs("Comp") & vbCrLf
End If

WScript.Echo s   ' Выводим сформированные строки
'*************  Конец *********************************************
Листинг 5.9. Доступ к параметрам командной строки запущенного сценария (VBScript) (html, txt)
Объект WshEnvironment

Объект WshEnvironment позволяет получить доступ к коллекции, содержащей переменные среды заданного типа (переменные среды операционной системы, переменные среды пользователя или переменные среды текущего командного окна). Этот объект можно создать с помощью свойства Environment объекта WshShell или одноименного его метода:

Set WshShell=WScript.CreateObject("WScript.Shell")
Set WshSysEnv=WshShell.Environment
Set WshUserEnv=WshShell.Environment("User")

Объект WshEnvironment имеет свойство Length, в котором хранится число элементов в коллекции (количество переменных среды), и методы Count и Item. Для того чтобы получить значение определенной переменной среды, в качестве аргумента метода Item указывается имя этой переменной в двойных кавычках. В следующем примере мы выводим на экран значение переменной среды PATH (листинг 5.10):

'********************************************************************
' Имя: Environment.vbs
' Язык: VBScript
' Описание: Работа с переменными среды
'********************************************************************
Dim WshShell, WshSysEnv
Set WshShell=WScript.CreateObject("WScript.Shell")
Set WshSysEnv=WshShell.Environment
WScript.Echo "Системный путь:",WshSysEnv.Item("PATH")
Листинг 5.10. Работа с переменными среды (VBScript) (html, txt)

Можно также просто указать имя переменной в круглых скобках после имени объекта:

WScript.Echo "Системный путь:",WshSysEnv("PATH")

Кроме этого у объекта WshEnvironment имеется метод Remove(strName), который удаляет заданную переменную среды.

Объект WshSpecialFolders

При установке Windows всегда автоматически создаются несколько специальных папок (например, папка для рабочего стола (Desktop) или папка для меню Пуск (Start)), путь к которым впоследствии может быть тем или иным способом изменен. Объект WshSpecialFolders обеспечивает доступ к коллекции, содержащей пути к специальным папкам Windows; задание путей к таким папкам может понадобиться, например, для создания непосредственно из сценария ярлыков на рабочем столе.

В Windows XP поддерживаются следующие имена специальных папок:

Объект WshSpecialFolders создается с помощью свойства SpecialFolders объекта WshShell:

var WshShell=WScript.CreateObject("WScript.Shell"),
    WshSpecFold=WshShell.SpecialFolders;

В листинге 5.11 приведен сценарий, формирующий список всех имеющихся в системе специальных папок.

'*****************************************************************
' Имя: SpecFold1.vbs
' Язык: VBScript
' Описание: Вывод названий всех специальных папок Windows
'*****************************************************************
Option Explicit

Dim WshShell, WshFldrs, SpecFldr, s  ' Объявляем переменные
' Создаем объект WshShell
Set WshShell = WScript.CreateObject("Wscript.Shell")
' Создаем объект WshSpecialFolders
Set WshFldrs = WshShell.SpecialFolders
s="Список всех специальных папок:" & vbCrLf & vbCrLf
' Перебираем все элементы коллекции WshFldrs
For Each SpecFldr In WshFldrs
  ' Формируем строки с путями к специальным папкам
  s=s & SpecFldr & vbCrLf
Next
WScript.Echo s
'*************  Конец *********************************************/
Листинг 5.11. Формирование списка всех специальных папок (VBScript) (html, txt)

Объект WshSpecialFolders также позволяет получить путь к конкретно заданной специальной папке. Например, в сценарии SpecFold2.vbs (листинг 5.12) на экран выводятся пути к папкам рабочего стола (Desktop), избранных ссылок (Favorites) и раздела Программы (Programs) меню Пуск (Run).

'******************************************************************
' Имя: SpecFold2.vbs
' Язык: VBScript
' Описание: Вывод названий заданных специальных папок Windows
'******************************************************************
Option Explicit

Dim WshShell, WshFldrs, s   ' Объявляем переменные
' Создаем объект WshShell
Set WshShell = WScript.CreateObject("Wscript.Shell")
' Создаем объект WshSpecialFolders
Set WshFldrs = WshShell.SpecialFolders
' Формируем строки с путями к конкретным специальным папкам
s="Некоторые специальные папки:" & vbCrLf & vbCrLf
s=s+"Desktop:"+WshFldrs("Desktop") & vbCrLf
s=s+"Favorites:"+WshFldrs("Favorites") & vbCrLf
s=s+"Programs:"+WshFldrs("Programs")
WScript.Echo s   ' Выводим сформированные строки на экран
'*************  Конец *********************************************/
Листинг 5.12. Доступ к определенным специальным папкам (VBScript) (html, txt)

Лекция 6. Сценарии WSH для доступа к файловой системе. Объектная модель FileSystemObject

Рассматриваются свойства и методы стандартного объекта FileSystemObject. Приводятся примеры сценариев WSH для выполнения основных операций с файловой системой

Сценарии WSH для доступа к файловой системе. Объектная модель FileSystemObject

Сценарии WSH позволяют получить полный доступ к файловой системе компьютера, в отличие от JScript- или VBScript-сценариев, внедренных в HTML-страницы, где в зависимости от уровня безопасности, который устанавливается в настройках браузера, те или иные операции могут быть запрещены.

Объекты для основных операций с файловой системой

Для работы с файловой системой из сценариев WSH предназначены восемь объектов, главным из которых является FileSystemObject. С помощью методов объекта FileSystemObject можно выполнять следующие основные действия:

С помощью свойств объектов Drive, Folder и File можно получить детальную информацию о тех элементах файловой системы, с которыми они ассоциированы. Объекты Folder и File также предоставляют методы для манипулирования файлами и каталогами (создание, удаление, копирование, перемещение); эти методы в основном копируют соответствующие методы объекта FileSystemObject.

Кроме этого имеются три объекта-коллекции: Drives, Folders и Files. Коллекция Drives содержит объекты Drive для всех имеющихся в системе дисков, Folders — объекты Folder для всех подкаталогов заданного каталога, Files — объекты File для всех файлов, находящихся внутри определенного каталога.

Наконец, из сценария можно читать информацию из текстовых файлов и записывать в них данные. Методы для этого предоставляет объект TextStream.

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

Таблица 6.1. Выполнение основных файловых операций
ОперацияИспользуемые объекты, свойства и методы
Получение сведений об определенном диске (тип файловой системы, метка тома, общий объем и количество свободного места и т.д.)Свойства объекта Drive. Сам объект Drive создается с помощью метода GetDrive объекта FileSystemObject
Получение сведений о заданном каталоге или файле (дата создания или последнего доступа, размер, атрибуты и т.д.)Свойства объектов Folder и File. Сами эти объекты создаются с помощью методов GetFolder и GetFile объекта FileSystemObject
Проверка существования определенного диска, каталога или файлаМетоды DriveExists, FolderExists и FileExists объекта FileSystemObject
Копирование файлов и каталоговМетоды CopyFile и CopyFolder объекта FileSystemObject, а также методы File.Copy и Folder.Copy
Перемещение файлов и каталоговМетоды MoveFile и MoveFolder объекта FileSystemObject, или методы File.Move и Folder.Move
Удаление файлов и каталоговМетоды DeleteFile и DeleteFolder объекта FileSystemObject, или методы File.Delete и Folder.Delete
Создание каталогаМетоды FileSystemObject.CreateFolder или Folders.Add
Создание текстового файлаМетоды FileSystemObject.CreateTextFile или Folder.CreateTextFile
Получение списка всех доступных дисковКоллекция Drives, содержащаяся в свойстве FileSystemObject.Drives
Получение списка всех подкаталогов заданного каталогаКоллекция Folders, содержащаяся в свойстве Folder.SubFolders
Получение списка всех файлов заданного каталогаКоллекция Files, содержащаяся в свойстве Folder.Files
Открытие текстового файла для чтения, записи или добавленияМетоды FileSystemObject.CreateTextFile или File.OpenAsTextStream
Чтение информации из заданного текстового файла или запись ее в негоМетоды объекта TextStream

Примеры сценариев

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

Получение сведений о диске

Доступ к свойствам заданного локального или сетевого диска можно получить с помощью объекта Drive, который возвращается методом GetDrive объекта FileSystemObject, а также может быть получен как элемент коллекции Drives.

В листинге 6.1 приведен сценарий DriveInfo.vbs, который выводит на экран некоторые свойства диска С.

'*******************************************************************
' Имя: DriveInfo.vbs                                               
' Язык: VBScript                                                   
' Описание: Вывод на экран свойств диска C                       
'*******************************************************************
'Объявляем переменные
Dim FSO,D,TotalSize,FreeSpace,s
'Создаем объект FileSystemObject
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
'Создаем объект Drive для диска C
Set D = FSO.GetDrive("C:")
s = "Информация о диске C:" & VbCrLf
'Получаем серийный номер диска
s = s &"Серийный номер: " & D.SerialNumber & VbCrLf
'Получаем метку тома диска
s = s & "Метка тома: " & D.VolumeName & VbCrLf
'Вычисляем общий объем диска в килобайтах
TotalSize = D.TotalSize/1024
s = s & "Объем: " & TotalSize & " Kb" & VbCrLf
'Вычисляем объем свободного пространства диска в килобайтах
FreeSpace = D.FreeSpace/1024
s = s & "Свободно: " & FreeSpace & " Kb" & VbCrLf
'Выводим свойства диска на экран
WScript.Echo s
'*************  Конец *********************************************
Листинг 6.1. Вывод информации о диске (VBScript) (html, txt)
Получение сведений о каталоге

Доступ к свойствам каталога обеспечивает объект Folder. Создать этот объект можно с помощью свойства RootFolder объекта Drive или методов GetFolder, GetParentFolder и GetSpecialFolder объекта FileSystemObject. Также объекты Folder могут быть получены как элементы коллекции Folders.

В сценарии FolderInfo.vbs на экран выводятся свойства каталога, из которого был запущен сценарий (листинги 6.2).

'*******************************************************************
' Имя: FolderInfo.vbs                                              
' Язык: VBScript                                                   
' Описание: Вывод на экран даты создания текущего каталога        
'*******************************************************************
Dim FSO,WshShell,FoldSize,s  'Объявляем переменные

'Создаем объект FileSystemObject
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
'Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")

'Определяем каталог, из которого был запущен сценарий
'(текущий каталог)
Set Folder = FSO.GetFolder(WshShell.CurrentDirectory)
'Получаем имя текущего каталога
s = "Текущий каталог: " & Folder.Name & VbCrLf
'Получаем дату создания текущего каталога
s = s & "Дата создания: " & Folder.DateCreated & VbCrLf
'Вычисляем размер текущего каталога в килобайтах
FoldSize=Folder.Size/1024
s = s & "Объем: " & FoldSize & " Kb" & VbCrLf
'Выводим информацию на экран
WScript.Echo s
'*************  Конец *********************************************
Листинг 6.2. Вывод информации о каталоге (VBScript) (html, txt)
Получение сведений о файле

Доступ ко всем свойствам файла обеспечивает объект File, создать который можно с помощью коллекции Files или метода GetFile объекта FileSystemObject.

В листинге 6.3 приведен сценарий FileInfo.vbs, в котором на экран выводятся некоторые свойства файла C:\boot.ini.

'*******************************************************************
' Имя: FileInfo.vbs                                                
' Язык: VBScript                                                   
' Описание: Вывод на экран некоторых свойств файла                
'*******************************************************************
Dim FSO,F,s   'Объявляем переменные

'Создаем объект FileSystemObject
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
'Создаем объект File
Set F = FSO.GetFile("C:\boot.ini")

'Получаем имя файла
s = "Файл: " & F.Name & VbCrLf
'Получаем дату создания файла
s = s & "Дата создания: " & F.DateCreated & VbCrLf
'Получаем тип файла
s = s & "Тип: " & F.Type & VbCrLf
'Выводим информацию на экран
WScript.Echo s
'*************  Конец *********************************************
Листинг 6.3. Вывод информации о файле (VBScript) (html, txt)
Проверка существования диска, каталога или файла

Для проверки существования диска, каталога и файла используются соответственно методы DriveExists, FolderExists и FileExists. В листинге 6.4 приведен сценарий IsExistsFile.vbs, в котором проверяется наличие на диске C файла boot.ini.

'******************************************************************
' Имя: IsExistsFile.vbs                                            
' Язык: VBScript                                                   
' Описание: Проверка существования файла                          
'*******************************************************************
Dim FSO,FileName 'Объявляем переменные

'Создаем объект FileSystemObject
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")

FileName = "C:\boot.ini"
if  FSO.FileExists(FileName)  Then
  'Выводим информацию на экран
  WScript.Echo "Файл " & FileName & " существует"
else
  'Выводим информацию на экран
  WScript.Echo "Файл " & FileName & " не существует" 
end if
'*************  Конец *********************************************
Листинг 6.4. Проверка существования файла (VBScript) (html, txt)
Получение списка всех имеющихся дисков

Каждому из дисков компьютера (включая подключенные сетевые диски и дисководы со сменными носителями) соответствует элемент коллекции Drives (объект Drive ). Таким образом, для построения списка дисков компьютера нужно в цикле перебрать все элементы коллекции Drives.

В листинге 6.5 приведен сценарий ListDrives.vbs, в котором на экран выводятся сведения обо всех доступных дисках.

'*******************************************************************
' Имя: ListDrives.vbs                                              
' Язык: VBScript                                                   
' Описание: Получение списка всех имеющихся дисков                
'*******************************************************************
'Объявляем переменные
Dim FSO,s,ss,Drives,D

'Создаем объект FileSystemObject
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
'Создаем коллекцию дисков, имеющихся в системе
Set Drives = FSO.Drives
s = ""

'Перебираем все диски в коллекции
For Each D In Drives
  'Получаем букву диска
  s = s & D.DriveLetter
  s = s & " - "
  if (D.DriveType = 3) then  'Проверяем, не является ли диск сетевым
    'Получаем имя сетевого ресурса
    ss = D.ShareName
  else 
    'Диск является локальным
    if (D.IsReady) then  'Проверяем готовность диска
      'Если диск готов, то получаем метку тома для диска
      ss = D.VolumeName
    else
      ss = "Устройство не готово"
    end if  
  s = s & ss & VbCrLf
  end if  
Next

'Выводим полученные строки на экран
WScript.Echo s
'*************  Конец *********************************************
Листинг 6.5. Построение списка всех имеющихся дисков (VBScript) (html, txt)
Получение списка всех подкаталогов заданного каталога

Для построения списка всех подкаталогов определенного каталога можно воспользоваться коллекцией Folders, которая хранится в свойстве SubFolders соответствующего объекта Folder и содержит объекты Folder для всех подкаталогов.

В листинге 6.6 приведен сценарий ListSubFold.vbs, в котором на экран выводятся названия всех подкаталогов каталога C:\Program Files.

'*******************************************************************
' Имя: ListSubFold.vbs                                             
' Язык: VBScript                                                   
' Описание: Получение списка всех подкаталогов заданного каталога 
'*******************************************************************
'Объявляем переменные
Dim FSO,F,SFold,SubFolders,Folder,s

'Создаем объект FileSystemObject
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
'Путь к каталогу
SFold = "C:\Program Files"
s = "Каталог " & SFold & VbCrLf
s = s & "Подкаталоги:" & VbCrLf
'Создаем объект Folder для каталога C:\Program Files
Set F=FSO.GetFolder(SFold)

'Создаем коллекцию подкаталогов каталога C:\Program Files
Set SubFolders = F.SubFolders

'Цикл по всем подкаталогам
For Each Folder In SubFolders
  'Добавляем строку с именем подкаталога
   s = s & Folder & VbCrLf
Next

'Выводим полученные строки на экран
WScript.Echo s
'*************  Конец *********************************************/
Листинг 6.6. Построение списка подкаталогов (VBScript) (html, txt)
Получение списка всех файлов заданного каталога

В свойстве Files объекта Folder, соответствующего определенному каталогу, хранится коллекция находящихся в этом каталоге файлов (объектов File ). В листинге 6.7 приведен сценарии ListFiles.vbs, выводящий на экран названия всех файлов, которые содержатся в специальной папке Мои документы.

'*******************************************************************
' Имя: ListFiles.vbs                                               
' Язык: VBScript                                                   
' Описание: Получение списка всех файлов заданного каталога       
'*******************************************************************
'Объявляем переменные
Dim FSO,F,File,Files,WshShell,PathList,s

'Создаем объект FileSystemObject
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
'Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
'Создаем объект WshSpecialFolders
Set WshFldrs = WshShell.SpecialFolders
'Определяем путь к папке Мои документы
PathList = WshFldrs.item("MyDocuments") & "\"
'Создаем объект Folder для папки Мои документы
Set F = FSO.GetFolder(PathList)
'Создаем коллекцию файлов каталога Мои документы
Set Files = F.Files
s = "Файлы из каталога " & PathList & VbCrLf
'Цикл по всем файлам
For Each File In Files
  'Добавляем строку с именем файла
  s = s & File.Name & VbCrLf
Next

'Выводим полученные строки на экран
WScript.Echo s
'*************  Конец *********************************************
Листинг 6.7. Построение списка файлов в каталоге (JScript) (html, txt)
Создание каталога

Создать новый каталог на диске можно либо с помощью метода CreateFolder объекта FileSystemObject, либо с помощью метода Add коллекции Folders. Оба эти метода используются в сценарии MakeFolder.vbs для создания в каталоге C:\Program Files подкаталогов Новая папка и Еще одна новая папка (листинг 6.8).

'*******************************************************************
' Имя: MakeFolder.vbs                                           
' Язык: VBScript                                                   
' Описание: Создание нового каталога                              
'*******************************************************************
'Объявляем переменные
Dim FSO, F, SubFolders

'Создаем объект FileSystemObject
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
'Создаем каталог C:\Program Files\Новая папка
FSO.CreateFolder("C:\Program Files\Новая папка")
'Создаем объект Folder для каталога C:\Program Files
Set F = FSO.GetFolder("C:\Program Files")
'Создаем коллекцию подкаталогов каталога C:\Program Files
Set SubFolders = F.SubFolders
'Создаем каталог C:\Program Files\Еще одна новая папка
SubFolders.Add "Еще одна новая папка"
'*************  Конец *********************************************
Листинг 6.8. Создание нового каталога (VBScript) (html, txt)
Создание текстового файла

Для создания текстового файла используется метод CreateTextFile объекта FileSystemObject, который имеет один обязательный текстовый параметр (путь к создаваемому файлу) и два необязательных логических параметра ( Overwrite и Unicode ).

Параметр Overwrite имеет значение в том случае, когда создаваемый файл уже существует. Если Overwrite равно True, то такой файл перепишется (старое содержимое будет утеряно), если же в качестве Overwrite указано False, то файл переписываться не будет. Если этот параметр вообще не указан, то существующий файл также не будет переписан.

Параметр Unicode указывает, в каком формате (ASCII или Unicode) следует создавать файл. Если Unicode равно True, то файл создается в формате Unicode, если же Unicode равно False или этот параметр вообще не указан, то файл создается в режиме ASCII.

В сценарии CreateTempFile.vbs (листинг 6.9) показано, каким образом можно создать файл со случайно выбранным именем (такие файлы часто используются для записи временных данных).

'*******************************************************************
' Имя: CreateTempFile.vbs                                                
' Язык: VBScript                                                   
' Описание: Создание временного файла со случайным именем         
'*******************************************************************
Dim FSO,FileName,F,s  'Объявляем переменные
'Создаем объект FileSystemObject
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
'Генерируем случайное имя файла
FileName = FSO.GetTempName
'Создаем файл с именем FileName
Set F = FSO.CreateTextFile(FileName, true) 
'Закрываем файл
F.Close
'Сообщаем о создании файла
WScript.Echo "Был создан файл " & FileName
'*************  Конец *********************************************
Листинг 6.9. Создание временного файла со случайным именем (VBScript) (html, txt)
Операции чтения и записи строк для текстового файла

Последовательный (строка за строкой) доступ к текстовому файлу обеспечивает объект TextStream. Методы этого объекта позволяют читать информацию из файла и записывать ее в него. Создается объект TextStream при открытии или создании текстового файла с помощью следующих методов:

Перечисленные ранее методы позволяют открывать файл в разных режимах ввода/вывода (за это отвечает параметр Iomode ) с использованием разных форматов (в соответствии со значением параметра Format ) (см. табл. 6.2, 6.3)

Таблица 6.2. Параметр Iomode
КонстантаЗначениеОписание
ForReading1Файл открывается только для чтения, записывать информацию в него нельзя
ForWriting2Файл открывается для записи. Если файл с таким именем уже существовал, то при новой записи его содержимое теряется
ForAppending8Файл открывается для добавления. Если файл уже существовал, то информация будет дописываться в конец этого файла
Таблица 6.3. Параметр Format
КонстантаЗначениеОписание
TristateUseDefault-2Файл открывается в формате, используемом системой по умолчанию
TristateTrue-1Файл открывается в формате Unicode
TristateFalse0Файл открывается в формате ASCII

В листинге 6.10 приведен сценарий TextFile.vbs, в котором создается файл test1.txt и в него записываются строка текста. После этого файл открывается для чтения, строка считывается из него и выводится на экран.

'*******************************************************************
' Имя: TextFile.vbs                                                
' Язык: VBScript                                                  
' Описание: Запись строк в текстовый файл и чтение из него     
'*******************************************************************
Dim FSO,F,TextStream,s  'Объявляем переменные
' Инициализируем константы
Const ForReading = 1, ForWriting = 2, TristateUseDefault = -2

' Создаем объект FileSystemObject
Set FSO=WScript.CreateObject("Scripting.FileSystemObject")
' Создаем в текущем каталоге файл test1.txt
FSO.CreateTextFile "test1.txt"
' Создаем объект File для файла test1.txt
set F=FSO.GetFile("test1.txt")
' Создаем объект TextStream (файл открывается для записи)
Set TextStream=F.OpenAsTextStream(ForWriting, TristateUseDefault)
' Записываем в файл строку
TextStream.WriteLine "Это первая строка"
' Закрываем файл
TextStream.Close
' Открываем файл для чтения
Set TextStream=F.OpenAsTextStream(ForReading, TristateUseDefault)
' Считываем строку из файла
s=TextStream.ReadLine
' Закрываем файл 
TextStream.Close
' Отображаем строку на экране
WScript.Echo "Первая строка из файла test1.txt:" & vbCrLf & vbCrLf & s
'*************  Конец *********************************************
Листинг 6.10. Запись информации в текстовый файл и чтение из него (VBScript) (html, txt)
Копирование и перемещение файлов и каталогов

Для копирования файлов/каталогов можно применять метод CopyFile/CopyFolder объекта FileSystemObject или метод Copy соответствующего этому файлу/каталогу объекта File/Folder. Перемещаются файлы/каталоги с помощью методов MoveFile/MoveFolder объекта FileSystemObject или метода Move соответствующего этому файлу/каталогу объекта File/Folder.

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

В листингах 6.11 и 6.12 приведен сценарий CopyFile.vbs, иллюстрирующий использование метода Copy. В этом сценарии на диске C создается файл TestFile.txt, который затем копируется на рабочий стол.

'*******************************************************************
' Имя: CopyFile.vbs                                                
' Язык: VBScript                                                   
' Описание: Создание и копирование файла                          
'*******************************************************************
'Объявляем переменные
Dim FSO,F,WshShell,WshFldrs,PathCopy

'Создаем объект FileSystemObject
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
'Создаем файл
Set F = FSO.CreateTextFile("C:\TestFile.txt", true)
'Записываем в файл строку
F.WriteLine "Тестовый файл"
'Закрываем файл
F.Close

'Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
'Создаем объект WshSpecialFolders
Set WshFldrs = WshShell.SpecialFolders
'Определяем путь к рабочему столу
PathCopy = WshFldrs.item("Desktop")+"\"
'Создаем объект File для файла C:\TestFile.txt
Set F = FSO.GetFile("C:\TestFile.txt")
'Копируем файл на рабочий стол
F.Copy PathCopy
'*************  Конец *********************************************
Листинг 6.11. Создание текстового файла и копирование его в другой каталог (VBScript) (html, txt)
Удаление файлов и каталогов

Для удаления файлов/каталогов можно применять метод DeleteFile/DeleteFolder объекта FileSystemObject или метод Delete соответствующего этому файлу/каталогу объекта File/Folder. Отметим, что при удалении каталога неважно, является ли он пустым или нет — удаление будет произведено в любом случае. Если же заданный для удаления файл/каталог не будет найден, то возникнет ошибка.

В листинге 6.12 приведен сценарий DeleteFile.vbs, в котором производится удаление предварительно созданного файла C:\TestFile.txt.

'*******************************************************************
' Имя: DeleteFile.vbs
' Язык: VBScript                                                   
' Описание: Создание и удаление файла                             
'*******************************************************************
'Объявляем переменные
Dim FSO,F,FileName

'Создаем объект FileSystemObject
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
'Задаем имя файла
FileName="C:\TestFile.txt"
'Создаем файл
Set F = FSO.CreateTextFile(FileName, true)
'Записываем в файл строку
F.WriteLine "Тестовый файл"
'Закрываем файл
F.Close
WScript.Echo "Файл создан"
FSO.DeleteFile FileName
WScript.Echo "Файл удален"
'*************  Конец *********************************************
Листинг 6.12. Создание и удаление файла (VBScript) (html, txt)

Лекция 7. WSH как средство взаимодействия с внешними программами

Обсуждаются способы запуска из сценариев WSH внешних процессов и подключения к внешним COM-объектам (серверам автоматизации). Рассматриваются примеры работы с объектными моделями программ Microsoft Word и Microsoft Excel

WSH как средство взаимодействия с внешними программами

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

Запуск приложений Windows

Из сценария WSH запустить другое приложение можно с помощью методов Run или Exec объекта WshShell.

При использовании метода Run для запускаемого приложения можно задать тип окна (при условии, что приложение поддерживает этот тип). Например, в результате выполнения следующих двух строк VBScript-кода:

Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "notepad",3

программа Блокнот (notepad.exe) будет запущена в максимизированном (развернутом на весь экран) окне.

Замечание

Метод Run всегда создает новый экземпляр запускаемого процесса, с его помощью нельзя ни повторно активизировать окно запущенного приложения (для этого используется метод AppActivate ), ни свернуть или развернуть его.

Другим вариантом запуска из сценария приложения Windows, является применение метода Exec. Этот метод запускает приложение, путь к которому указан как параметр метода, и возвращает объект WshScriptExec. Например:

Set WshShell = WScript.CreateObject("WScript.Shell")
Set theNotepad = WshShell.Exec("notepad")

Замечание

При подобном запуске приложения, в отличие от метода Run, нельзя задать тип окна.

Объект WshScriptExec позволяет контролировать ход выполнения запущенного приложения с помощью свойства Status — если Status равен 0, то приложение выполняется, если Status равен 1, то приложение завершено. Кроме этого, используя метод Terminate, можно принудительно завершить работу того приложения, которому соответствует объект WshScriptExec.

В листинге 7.1 приведен сценарий на языке VBScipt, в котором с помощью метода Exec запускается Блокнот (notepad.exe); ссылка на соответствующий объект WshScriptExec сохраняется в переменной theNotepad:

Set theNotepad = WshShell.Exec("notepad")

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

'*******************************************************************
' Имя: ExecWinApp.vbs
' Язык: VBScript
' Описание: Запуск и закрытие приложение (объект WshScriptExec)
'*******************************************************************
Option Explicit

Dim WshShell,theNotepad,Res,Text,Title   ' Объявляем переменные
' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
WScript.Echo "Запускаем Блокнот"
' Запускаем приложение (создаем объект WshScriptExec)
Set theNotepad = WshShell.Exec("notepad")
WScript.Sleep 500   ' Приостанавливаем выполнение сценария
Text="Блокнот запущен (Status=" & theNotepad.Status & ")" & vbCrLf _
      & "Закрыть Блокнот?"
Title=""
' Выводим диалоговое окно на экран
Res=WshShell.Popup(Text,0,Title,vbQuestion+vbYesNo)
' Определяем, какая кнопка нажата в диалоговом окне
If Res=vbYes Then
  theNotepad.Terminate ' Прерываем работу Блокнота
  ' Приостанавливаем выполнение сценария, для того чтобы Блокнот
  ' успел закрыться
  WScript.Sleep 100
  WScript.Echo "Блокнот закрыт (Status=" & theNotepad.Status & ")"
End If
'*************  Конец *********************************************/
Листинг 7.1. Запуск и принудительное закрытие приложения (VBScript) (html, txt)

Переключение между приложениями, имитация нажатий клавиш

Производить переключение между окнами нескольких запущенных приложений позволяет метод AppActivate объекта WshShell. В качестве аргумента этого метода нужно указывать либо заголовок активизируемого окна, либо идентификатор процесса (Process ID, PID), который запущен в данном окне. Предпочтительным является использование PID, получаемого с помощью свойства ProcessID объекта WshScriptExec, соответствующего активизируемому приложению. Недостатки применения заголовка окна в методе AppActivate:

Активизировав то или иное окно, в котором выполняется приложение Windows, можно из сценария сымитировать нажатия клавиш в этом окне. Для этого используется метод SendKeys объекта WshShell.

Рассмотрим пример сценария Run&ExecWinApp.vbs (листинг 7.2), в котором запускается Калькулятор (calc.exe) и в его окно с помощью SendKeys последовательно посылаются нажатия клавиш <1>, <+>, <2> и <Enter>:

Set theCalculator = WshShell.Exec("calc")
WScript.Sleep 500
WshShell.AppActivate theCalculator.ProcessID
WshShell.SendKeys "1{+}"
WshShell.SendKeys "2"
WshShell.SendKeys "~"  ' Клавиша <Enter>

Затем выполнение сценария приостанавливается на 1 секунду, чтобы результат вычислений был виден на экране и результат вычислений (символ "3") копируется в буфер Windows с помощью "нажатия" клавиш <Ctrl>+<C>:

WshShell.SendKeys "^c"

После этого на экран выводится сообщение о том, что Калькулятор будет закрыт, в результате чего окно Калькулятора теряет фокус. Для того чтобы вновь активизировать это окно, используется метод AppActivate, параметром которого служит PID Калькулятора:

WshShell.AppActivate theCalculator.ProcessID

Для того чтобы закрыть окно Калькулятора, в него посылаются нажатия клавиш <Alt>+<F4>:

WshShell.SendKeys "%{F4}"

После закрытия Калькулятора запускается Блокнот (notepad.exe) и в него записываются результаты работы Калькулятора (вставка из буфера вычисленной суммы производится с помощью "нажатий" <Ctrl>+<V>):

WshShell.Run "notepad"
WScript.Sleep 1000
WshShell.AppActivate "notepad"
WshShell.SendKeys "1{+}2="
WshShell.SendKeys "^v"
WshShell.SendKeys " {(}c{)} Calculator"
'*******************************************************************
' Имя: Run&ExecWinApp.vbs
' Язык: VBScript
' Описание: Запуск двух приложений и обмен данными между ними
'*******************************************************************
Option Explicit

Dim WshShell, theCalculator  ' Объявляем переменные
' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
WScript.Echo("Запускаем калькулятор и" & vbCrLf & "считаем 1+2")
' Создаем объект WshScript (запускаем Калькулятор)
Set theCalculator = WshShell.Exec("calc")
' Приостанавливаем выполнение сценария, для того чтобы
' окно Калькулятора успело появиться на экране
WScript.Sleep 500
' Активизируем окно Калькулятора
WshShell.AppActivate theCalculator.ProcessID
' Посылаем нажатия клавиш в окно Калькулятора
WshShell.SendKeys "1{+}"
WshShell.SendKeys "2"
WshShell.SendKeys "~"    ' Клавиша <Enter>
WScript.Sleep 500
' Копируем результат вычисления в буфер Windows (<Ctrl>+C)
WshShell.SendKeys "^c"
' Выводим сообщение (активное окно меняется)
WScript.Echo "Закрываем калькулятор"
' Активизируем окно Калькулятора
WshShell.AppActivate theCalculator.ProcessID
' Закрываем окно Калькулятора (<Alt>+<F4>)
WshShell.SendKeys "%{F4}"
WScript.Echo "Запускаем Блокнот и копируем туда результат"
WshShell.Run "notepad"     ' Запускаем Блокнот
' Приостанавливаем выполнение сценария, для того чтобы
' окно Блокнота успело появиться на экране
WScript.Sleep 1000
WshShell.AppActivate "notepad"    ' Активизируем окно Блокнота
' Посылаем нажатия клавиш в окно Блокнота
WshShell.SendKeys "1{+}2="
' Вставляем содержимое буфера Windows (<Ctrl>+V)
WshShell.SendKeys "^v"
' Выводим в окно Блокнота оставшуюся информацию
WshShell.SendKeys " {(}c{)} Calculator"
'*************  Конец *********************************************
Листинг 7.2. Запуск двух приложений и обмен данными между ними (VBScript) (html, txt)

Запуск независимых консольных приложений и команд Windows

Для запуска независимых, т. е. работающих в отдельном адресном пространстве и использующих свою копию переменных среды, консольных приложений или внешних (представленных исполняемыми файлами на жестком диске) команд Windows используется метод Run объекта WshShell. При этом выполнение сценария можно приостановить до окончания работы запущенного приложения, а затем проанализировать код выхода этого приложения (для этого третий параметр метода Run должен равняться True ). Соответствующий пример сценария приведен в листинге 7.3.

'*******************************************************************
' Имя: RunConApp.vbs
' Язык: VBScript
' Описание: Запуск независимого консольного приложения и
'           определение его кода выхода
'*******************************************************************
Option Explicit

Dim WshShell, Code   ' Объявляем переменные
' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
' Запускаем утилиту xcopy с ключом "/?" и ожидаем окончания ее работы
Code=WshShell.Run("xcopy /?",1,true)
' Печатаем полученный код возврата
WScript.Echo "Код возврата: ", Code
'*************  Конец *********************************************/
Листинг 7.3. Запуск независимого консольного приложения (VBScript) (html, txt)

Для выполнения внутренней команды Windows нужно запустить командный интерпретатор cmd.exe и передать ему в качестве параметра нужную команду. Для того чтобы при вызове командного интерпретатора не заботиться о полном пути к cmd.exe, нужно использовать переменную среды COMSPEC.

Замечание

Для получения значения переменной среды ее имя нужно окружить знаками % (например, %COMSPEC% ).

В листингах 7.4 приведен сценарий, в котором запускаются внутренние команды COPY /? (вызов встроенной справки для COPY ) и DIR %WINDIR% (вывод содержимого системного каталога Windows).

При этом окно, в котором выполняется команда COPY /?, не закрывается после завершения этой команды, т. к. при запуске командного интерпретатора был указан ключ /k, а информация, выводимая командой DIR %WINDIR%, перенаправляется в файл windir.txt, после чего командное окно закрывается, т. к. для командного интерпретатора в этом случае был указан ключ /c.

'*******************************************************************
' Имя: RunDOSCom.vbs
' Язык: VBScript
' Описание: Выполнение внутренних команд Windows
'*******************************************************************
Option Explicit

Dim WshShell, Code   ' Объявляем переменные
' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
' Запускаем внутреннюю команду COPY
WshShell.Run "%COMSPEC% /k copy /?",1
' Запускаем внутреннюю команду DIR
WshShell.Run "%COMSPEC% /c dir %WINDIR% > windir.txt",1
'*************  Конец *********************************************/
Листинг 7.4. Запуск внутренней команды Windows (VBScript) (html, txt)

Запуск дочерних консольных приложений и команд DOS, использование их входных и выходных потоков

Консольное приложение или команду DOS можно запустить из сценария как дочернюю задачу, т. е. с теми же переменными среды, что у процесса-родителя. При этом информация, выводимая дочерним процессом, на экран дублироваться не будет, однако из родительского сценария можно считывать информацию из выходного потока и посылать данные во входной поток дочерней задачи (это напоминает конвейеризацию команд Windows, при которой данные выходного потока одной команды поступают во входной поток другой команды, например DIR | MORE ). Таким образом, из сценария можно запускать ту или иную утилиту командной строки и обрабатывать выводимые ей данные; иногда таким образом получить нужную информацию бывает проще и быстрее, чем при использовании объектной модели WSH или другого сервера автоматизации.

В качестве примера рассмотрим сценарий ExecConApp.vbs (листинг 7.5), который выводит на экран общее количество файлов в текущем каталоге и их имена. Данную информацию можно получить в сеансе командной строки с помощью команды DIR /B. Поэтому в сценарии мы запустим в качестве дочернего процесса внутреннюю команду DIR с ключом /B:

Set ObjExec=WshShell.Exec("%COMSPEC% /c dir /b")

и полностью считаем данные, появляющиеся в выходном потоке этого процесса. Для этого в цикле вызывается метод ReadAll, считывающий всю информацию, имеющуюся к тому времени в потоке StdOut объекта ObjExec, в переменную s:

IsBreak=False
Do While True  ' Бесконечный цикл
  ' Проверяем, достигнут ли конец выходного потока команды DIR
  If (Not ObjExec.StdOut.AtEndOfStream) Then
    ' Считываем полностью выходной поток команды DIR
    s=s+ObjExec.StdOut.ReadAll
  End If
  If IsBreak Then
    Exit Do  ' Выходим из цикла
  End If
  ' Проверяем, не завершилось ли выполнение DIR
  If ObjExec.Status=1 Then
    IsBreak=True
  Else
    WScript.Sleep 100 ' Приостанавливаем сценарий на 0,1 сек
  End If
Loop

Родительский и дочерний процессы работают асинхронно, поэтому пока команда DIR не перестанет выдавать данные, т. е. пока свойство Status объекта ObjExec не станет равным 1, выполнение сценария с помощью метода WScript.Sleep периодически приостанавливается на 0,1 секунды.

После того как считаны все данные из выходного потока команды DIR (свойство ObjExec.StdOut.AtEndOfStream равно True ), происходит выход из цикла и формирование из переменной s массива выведенных строк:

ArrS=Split(s,vbCrLf)  ' Формируем массив строк

Теперь остается подсчитать количество файлов в каталоге, которое на единицу меньше количества строк в массиве ArrS:

ColFiles=UBound(ArrS)  ' Количество файлов в текущем каталоге
и вывести нужные строки на экран:
WScript.StdOut.WriteLine "Всего файлов в текущем каталоге: " & ColFiles
For i=0 To ColFiles-1 
  WScript.StdOut.WriteLine ArrS(i)  ' Выводим строки на экран
Next
'*******************************************************************
' Имя: ExecConApp.vbs
' Язык: VbScript
' Описание: Запуск дочернего консольного приложения
'*******************************************************************
Option Explicit
' Объявляем переменные
Dim ObjExec,WshShell,s,IsBreak,ArrS,ColFiles,i
' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
' Запускаем команду DIR
Set ObjExec=WshShell.Exec("%COMSPEC% /c dir /b")
s=""
IsBreak=False
Do While True  ' Бесконечный цикл
  ' Проверяем, достигнут ли конец выходного потока команды DIR
  If (Not ObjExec.StdOut.AtEndOfStream) Then
    ' Считываем полностью выходной поток команды DIR
    s=s+ObjExec.StdOut.ReadAll
  End If
  If IsBreak Then
    Exit Do  ' Выходим из цикла
  End If
  ' Проверяем, не завершилось ли выполнение DIR
  If ObjExec.Status=1 Then
    IsBreak=True
  Else
    WScript.Sleep 100 ' Приостанавливаем сценарий на 0,1 сек
  End If
Loop
ArrS=Split(s,vbCrLf)  ' Формируем массив строк
ColFiles=UBound(ArrS)  ' Количество файлов в текущем каталоге
WScript.StdOut.WriteLine "Всего файлов в текущем каталоге: " & ColFiles
For i=0 To ColFiles-1
  WScript.StdOut.WriteLine ArrS(i)  ' Выводим строки на экран
Next
'*************  Конец *********************************************
Листинг 7.5. Запуск дочернего консольного приложения (VBScript) (html, txt)

Использование внешних серверов автоматизации

Одна из наиболее полезных возможностей сценариев WSH – управление работой внешних серверов автоматизации (программ, предоставляющих свои службы и интерфейсы для использования другими приложениями). Самые распространенные и часто используемые серверы автоматизации в Windows – это приложения пакета Microsoft Office. Мы рассмотрим на примерах, каким образом можно выводить из сценариев WSH информацию в две наиболее распространенные программы этого пакета: Microsoft Word и Microsoft Excel.

Объектные модели Microsoft Word и Excel

Для того, чтобы использовать из сценариев WSH те возможности, которые поддерживают программы Word и Excel, необходимо знать, какие именно объекты предоставляются для внешнего использования этими серверами автоматизации и как объекты соотносятся друг с другом. Хотя объектные модели различных приложений Microsoft Office довольно сложны, они похожи друг на друга, причем для практических целей достаточно понять принцип работы с несколькими ключевыми объектами. Здесь мы не будем останавливаться на подробном рассмотрении свойств и методов объектов Word и Excel, а лишь кратко упомянем, какие именно объекты будут использоваться в рассмотренных ниже примерах сценариев.

На самом верхнем уровне объектной модели Word находится объект Application, который представляет непосредственно само приложение Word и содержит (в качестве свойств) все остальные объекты. Таким образом, объект Application используется для получения доступа к любому другому объекту Word.

Семейство Documents является свойством объекта Application и содержит набор объектов Document, каждый из которых соответствует открытому в Word документу. Класс Documents понадобится нам в сценариях для создания новых документов. Объект Document содержит в качестве своих свойств семейства различных объектов документа: символов (Characters), слов (Words), предложений (Sentences), параграфов (Paragraphs), закладок (Bookmarks) и т.д.

Объект Selection позволяет работать с выделенным фрагментом текста (этот фрагмент может быть и пустым). Таким образом, можно сказать, что объект Selection открывает путь в документ, так как он предоставляет доступ к выделенному фрагменту документа. В частности, у объекта Selection имеется метод TypeText(Text), с помощью которого можно вставлять текст в документ. Используя свойства этого объекта (которые, в свою очередь, могут являться объектами со своими свойствами), можно управлять параметрами выделенного фрагмента, например, устанавливать нужный размер и гарнитуру шрифта, выравнивать параграфы по центру и т.п.

Объектная модель Excel построена по тому же принципу, что и объектная модель Word. Основным объектом, содержащим все остальные, является Application. Напомним, что отдельные файлы в Excel называются рабочими книгами. Семейство Workbooks в Excel является аналогом семейства Documents в Word и содержит набор объектов Workbook (аналог объекта Document в Word), каждый из которых соответствует открытой в Excel рабочей книге. Новая рабочая книга создается с помощью метода Add() объекта Workbooks.

Для доступа к ячейкам активного рабочего листа Excel используется свойство Cells объекта Application. Для получения или изменения значения отдельной ячейки применяется конструкция Cells(row,column).Value, где row и column являются соответственно номерами строки и столбца, на пересечении которых находится данная ячейка.

В Excel, как и в Word, имеется объект Selection, позволяющий работать с выделенным фрагментом электронной таблицы. Самым простым способом выделить диапазон ячеек активного рабочего листа является использование метода Select() объекта Range. Например, выражение Range("A1:C1").Select() позволяет выделить три смежные ячейки: "A1", "B1" и "C1".

Для того, чтобы понять, какой именно объект Word или Excel нужно использовать для решения той или иной задачи, часто проще всего бывает проделать в соответствующем приложении необходимые манипуляции вручную, включив предварительно режим записи макроса. В результате мы получим текст макроса на языке VBA (Visual Basic for Applications), из которого будет ясно, какие методы и с какими параметрами нужно вызывать и какие значения нужно присваивать свойствам объектов. В качестве простой иллюстрации проделаем следующие действия. Запустим Word, запустим Macro Recorder (Сервис|Макрос|Начать запись… (Tools|Macros|Record…)), назовем новый макрос "Пример1" и нажмем на кнопку "Ok". После этого напишем в документе слово "Пример" и прекратим запись макроса. Теперь можно посмотреть содержимое записанного макроса. Для этого нужно выбрать пункт Макросы… (Macroses…) в меню Сервис|Макрос (Tools|Macros), выделить макрос "Пример1" в списке всех доступных макросов и нажать кнопку Изменить (Edit). В открывшемся окне редактора Visual Basic появится текст макроса:

Sub Пример1()
'
' Пример1 Макрос
' Макрос записан 12.09.07 Андрей Владимирович Попов
'
    Selection.TypeText Text:="Пример"
End Sub

Как мы видим, для печати слова в документе был использован метод TypeText объекта Selection.

Макросы в Excel записываются и редактируются аналогичным образом.

Взаимодействие с Microsoft Word

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

В любом случае в используемый метод или функцию в качестве параметра передается программный идентификатор объекта ( ProgID ), заключенный в скобки. Пример на языке VBScript:

Set WA=WScript.CreateObject("Word.Application")

Перед точкой в ProgID стоит имя библиотеки типов (type library) для объекта, которая может существовать как в виде отдельного файла с расширением tlb, так и в виде части файла с исполняемым кодом объекта (библиотека типов, содержащая сведения о COM-объекте, регистрируется в системном реестре при установке приложения, использующего этот объект). После точки в ProgID указывается имя класса, содержащего свойства и методы, доступные для использования другими приложениями.

Выполняя метод CreateObject, интерпретатор сценария через ProgID получает из системного реестра путь к файлам нужной библиотеки типов. Затем с помощью этой библиотеки в память загружается экземпляр запрашиваемого объекта, и его интерфейсы становятся доступными для использования в сценарии. Ссылка на созданный объект сохраняется в переменной; в дальнейшем, используя эту переменную, мы получаем доступ к свойствам и методам объекта, а также к его вложенным объектам (если они имеются).

Примеры управления приложением Microsoft Word из сценариев приведен в листинге 7.6. Сначала создается главный объект Word.Application, который запускает приложение Microsoft Word:

Set WA=WScript.CreateObject("Word.Application")

Затем создается новый пустой документ, в результате в переменную WD заносится ссылка на объект Document:

Set WD=WA.Documents.Add()

Наконец, в переменную Sel заносится ссылка на объект Selection, с помощью которого можно задать тип и размер шрифта, тип выравнивания абзацев и напечатать в документе строки текста:

Set Sel=WA.Selection;

В результате выполнения сценария PrintInWord.vbs в новом документе Microsoft Word печатаются две строки текста, после чего с помощью метода PrintOut объекта Document содержимое документа выводится на принтер:

WD.PrintOut();
'*******************************************************************
' Имя: PrintInWord.vbs
' Язык: VBScript
' Описание: Использование из сценария внешнего объекта
'           автоматизации (Microsoft Word)
'*******************************************************************
Option Explicit

Dim WA,WD,Sel  ' Объявляем переменные
'Создаем объект¬–приложение Microsoft Word
Set WA=WScript.CreateObject("Word.Application")
' Можно было использовать конструкцию
' Set WA=CreateObject("Word.Application")

Set WD=WA.Documents.Add  'Создаем новый документ (объект Document)
WA.Visible=true  ' Делаем Word видимым
Set Sel=WA.Selection  'Создаем объект Selection
Sel.Font.Size=14 'Устанавливаем размер шрифта
Sel.ParagraphFormat.Alignment=1  'Выравнивание по центру
Sel.Font.Bold=true  'Устанавливаем полужирный шрифт
Sel.TypeText "Привет!" & vbCrLf  'Печатаем строку текста
Sel.Font.Bold=false  'Отменяем полужирный шрифт
Sel.ParagraphFormat.Alignment=0  'Выравнивание по левому краю
'Печатаем строку текста
Sel.TypeText "Эти строки напечатаны с помощью WSH."
WD.PrintOut   'Выводим документ на принтер
'*************  Конец *********************************************
Листинг 7.6. Использование сервера автоматизации Microsoft Word (VBScript) (html, txt)
Взаимодействие с Microsoft Excel

В качестве примера управления сервером автоматизации Microsoft Excel рассмотрим сценарий PrintInExcel.vbs (листинг 7.7). Как и в случае с Microsoft Word, здесь сначала создается главный объект Excel.Application, который запускает приложение Microsoft Excel:

Set XL=WScript.CreateObject("Excel.Application")

Затем открывается новая рабочая книга:

XL.WorkBooks.Add

Ширина первого и второго столбца делается равной 40 пунктам, а третьей – 10 пунктам:

'Устанавливаем нужную ширину колонок
XL.Columns(1).ColumnWidth = 40
XL.Columns(2).ColumnWidth = 40
XL.Columns(3).ColumnWidth = 10

В столбцы первой строки записываются обозначения столбцов ("Фамилия", "Имя", "Телефон"), причем данный текст выделяется полужирным шрифтом:

'Печатаем в ячейки текст
XL.Cells(1,1).Value="Фамилия"
XL.Cells(1,2).Value="Имя"
XL.Cells(1,3).Value="Телефон"
'Выделяем три ячейки
XL.Range("A1:C1").Select
'Устанавливаем полужирный текст для выделенного диапазона
XL.Selection.Font.Bold = true
Во вторую строку заносятся данные для каждого столбца:
'Печатаем в ячейки текст
XL.Cells(2,1).Value="Иванов"
XL.Cells(2,2).Value="Иван"
XL.Cells(2,3).Value="555555"
'*******************************************************************
' Имя: PrintInExcel.vbs
' Язык: VBScript
' Описание: Использование из сценария внешнего объекта
'           автоматизации (Microsoft Excel)
'*******************************************************************
Option Explicit
                            	
Dim XL  ' Объявляем переменные

'Создаем объект-приложение Microsoft Excel	
Set XL=WScript.CreateObject("Excel.Application")
'Делаем окно Microsoft Excel видимым
XL.Visible=true
'Открываем новую рабочую книгу
XL.WorkBooks.Add
'Устанавливаем нужную ширину колонок
XL.Columns(1).ColumnWidth = 40
XL.Columns(2).ColumnWidth = 40
XL.Columns(3).ColumnWidth = 10
'Печатаем в ячейки текст
XL.Cells(1,1).Value="Фамилия"
XL.Cells(1,2).Value="Имя"
XL.Cells(1,3).Value="Телефон"
'Выделяем три ячейки
XL.Range("A1:C1").Select
'Устанавливаем полужирный текст для выделенного диапазона
XL.Selection.Font.Bold = true
'Печатаем в ячейки текст
XL.Cells(2,1).Value="Иванов"
XL.Cells(2,2).Value="Иван"
XL.Cells(2,3).Value="555555"
'*************  Конец *********************************************
Листинг 7.7. Использование сервера автоматизации Microsoft Excel (VBScript) (html, txt)

Лекция 8. Сценарии WSH для доступа к службе каталогов АDSI

Рассматривается стандартная для операционной системы Windows служба каталогов Active Directory Service Interface (ADSI). Приводятся примеры сценариев WSH, использующих ADSI для управления учетными записями пользователей и групп

Сценарии WSH для доступа к службе каталогов АDSI

Обсудим сначала термины "каталог" и "служба каталога", которые будут использоваться в этом разделе. Под каталогом в общем смысле этого слова подразумевается источник информации, в котором хранятся данные о некоторых объектах. Например, в телефонном каталоге хранятся сведения об абонентах телефонной сети, в библиотечном каталоге — данные о книгах, в каталоге файловой системы — информация о находящихся в нем файлах.

Что касается компьютерных сетей (локальных или глобальных), здесь также уместно говорить о каталогах, содержащих объекты разных типов: зарегистрированные пользователи, доступные сетевые принтеры и очереди печати и т.д. Для пользователей сети важно уметь находить и использовать такие объекты (а их в крупной сети может быть огромное количество), администраторы же сети должны поддерживать эти объекты в работоспособном состоянии. Под службой каталога (directory service) понимается та часть распределенной компьютерной системы (компьютерной сети), которая предоставляет средства для поиска и использования имеющихся сетевых ресурсов. Другими словами, служба каталога — это единое образование, объединяющее данные об объектах сети и совокупность служб, осуществляющих манипуляцию этими данными.

В гетерогенной (неоднородной) компьютерной сети могут одновременно функционировать несколько различных служб каталогов, например, NetWare Bindery для Novell Netware 3.x, NDS для Novell NetWare 4.x/5.x, Windows Directory Service для Windows NT 4.0 или Active Directory для Windows 2000/2003. Естественно, для прямого доступа к разным службам каталогов приходится использовать разные инструментальные средства, что усложняет процесс администрирования сети в целом. Для решения этой проблемы можно применить технологию ADSI (Active Directory Service Interface) фирмы Microsoft, которая предоставляет набор объектов ActiveX, обеспечивающих единообразный, не зависящий от конкретного сетевого протокола, доступ к функциям различных каталогов. Объекты ADSI включаются в операционные системы Windows 2000/XP и выше.

Для того, чтобы находить объекты в каталоге по их именам, необходимо определить для этого каталога пространство имен (namespace). Скажем, файлы на жестком диске находятся в пространстве имен файловой системы. Уникальное имя файла определяется расположением этого файла в пространстве имен, например:

C:\Windows\Command\command.com

Пространство имен службы каталогов также предназначено для нахождения объекта по его уникальному имени, которое обычно определяется расположением этого объекта в каталоге, где он ищется. Разные службы каталогов используют различные виды имен для объектов, которые они содержат. ADSI определяет соглашение для имен, с помощью которых можно однозначно идентифицировать любой объект в гетерогенной сетевой среде. Такие имена называются строками связывания (binding string) или строками ADsPath и состоят из двух частей. Первая часть имени определяет, к какой именно службе каталогов (или, другими словами, к какому именно провайдеру ADSI) мы обращаемся, например:

Вторая часть строки ADsPath определяет расположение объекта в конкретном каталоге. Приведем несколько примеров полных строк ADsPath:

"LDAP://ldapsrv1/CN=Popov,DC=DEV,DC=MSFT,DC=COM"
"WinNT://Domain1/Server1,Computer"
"WinNT://Domain1/Popov"
"NDS://TreeNW/O=SB/CN=Kazakov"
"NWCOMPAT://NWServer/MyNw3xPrinter"

В этом разделе мы подробно рассмотрим несколько простых сценариев, использующих объекты ADSI для автоматизации некоторых распространенных задач администрирования на отдельной рабочей станции с операционной системой Windows XP; поняв принцип их работы, вы без труда сможете написать аналогичные сценарии для локальной сети, которая функционирует, скажем, под управлением Active Directory или контроллера домена с Windows NT 4.0. Напомним, что на выделенном компьютере с Windows XP имеется база данных, содержащая информацию обо всех локальных пользователях этого компьютера. Пользователи компьютера определяются своими атрибутами (имя регистрации, полное имя, пароль и т.п.) и могут объединяться в группы. Ниже мы приведем примеры сценариев WSH, с помощью которых можно:

Связывание с нужным объектом каталога

Первым шагом для доступа к пространству имен любого каталога в целях получения информации о его объектах или изменения свойств этих объектов, является связывание (binding) с нужным объектом ADSI.

Рассмотрим вначале, каким образом формируется строка связывания для доступа к объектам отдельной рабочей станции с операционной системой Windows XP. В общем виде эта строка имеет следующий формат:

"WinNT:[//ComputerName[/ObjectName[,className]]]"

Здесь параметр ComputerName задает имя компьютера, ObjectName — имя объекта (это может быть имя группы, пользователя, принтера, сервиса и т.п.), className — класс объекта. Возможными значениями параметра className являются, например, group (группа пользователей), user (пользователь), printer (принтер) или service (сервис Windows XP).

Указав в качестве строки ADsPath просто "WinNT:", можно выполнить связывание с корневым объектом-контейнером, содержащим все остальные объекты службы каталога.

Приведем несколько примеров строк связывания для доступа к различным объектам компьютера Windows XP (табл. 8.1).

Таблица 8.1. Варианты строк связывания на компьютере Windows XP
Строка ADsPath Описание
"WinNT:"Строка для связывания с корневым объектом пространства имен
"WinNT://404_Popov"Строка для связывания с компьютером 404_Popov
"WinNT://404_Popov/Popov,user"Строка для связывания с пользователем Popov компьютера 404_Popov
"WinNT://404_Popov/BankUsers, group"Строка для связывания с группой BankUsers на компьютере 404_Popov

Для того, чтобы из сценария WSH использовать объект ADSI, соответствующий сформированной строке связывания, необходимо применить функцию GetObject языка JScript или VBScript, которая возвращает ссылку на объект ActiveX, находящийся во внешнем каталоге. Например (язык VBScript):

Set objNameSpace = GetObject("WinNT:")
Set objComputer = GetObject("WinNT://404_Popov")
Set objUser = GetObject("WinNT://Popov/Popov,user")
Set objGroup = GetObject("WinNT://Popov/BankUsers, group")

Замечание

Во всех рассмотренных ранее сценариях для создания объектов ActiveX мы пользовались методами CreateObject и GetObject объекта WScript или объектом ActiveXObject языка JScript. Для связывания же с объектом ADSI нужно использовать именно функцию GetObject языка JScript (или VBScript)!

Перейдем теперь к рассмотрению конкретных примеров сценариев, использующих объекты ADSI.

Список всех доступных доменов в локальной сети

В листинге 8.1 приведен сценарий ListDomains.vbs, в котором создается список всех доменов, доступных в сети.

В рассматриваемом сценарии производятся следующие действия. Сначала создается корневой объект objNameSpace класса Namespace для провайдера Windows NT, который содержит все остальные объекты службы каталога:

Set objNameSpace = GetObject("WinNT:")

Затем с помощью свойства Filter из коллекции ObjNameSpace выделяются все содержащиеся в ней объекты класса Domain:

objNameSpace.Filter = Array("domain")

В цикле For Each … In … выполняется перебор всех элементов коллекции, которые являются объектами класса Domain ; название домена, хранящееся в свойстве Name, добавляется (вместе с символом разрыва строки) в переменную strResult. Сформированная таким образом переменная strResult выводится на экран с помощью метода Echo объекта WScript.

'*******************************************************************
' Имя: ListDomains.vbs                                              
' Язык: VBScript                                                    
' Описание: Вывод на экран списка всех доменов локальной сети     
'*********************************************************************
Option Explicit

'Объявляем переменные
Dim objNameSpace        ' Корневой объект Namespace
Dim objDomain           ' Экземпляр объекта Domain
Dim strResult           ' Строка для вывода на экран

'Связываемся с корневым объектом Namespace
Set objNameSpace = GetObject("WinNT:")
'Устанавливаем фильтр для выделения объектов-доменов
objNameSpace.Filter = Array("domain")

strResult = "Все доступные домены в сети:" & vbCrLf & vbCrLf

' Перебираем элементы коллекции 
For Each objDomain In objNameSpace
  'Формируем строку с именами доменов
  strResult = strResult & objDomain.Name & vbCrLf
Next

'Вывод информацию на экран
WScript.Echo strResult
'*************  Конец *********************************************
Листинг 8.1. Вывод на экран списка всех доменов локальной сети (html, txt)

Создание пользователя и группы на рабочей станции

В сценарии AddUser.vbs, который приведен в листинге 8.2, для создания нового пользователя на рабочей станции выполняются следующие шаги. Во-первых, производится связывание с нужным компьютером (в нашем примере это рабочая станция с именем Popov), то есть создается экземпляр objComputer объекта Computer:

Set objComputer = GetObject("WinNT://Popov")

Во-вторых, создается экземпляр UserObj объекта User для нового пользователя. Для этого используется метод Create() объекта Computer ; в качестве параметров этого метода указывается имя класса "user" и имя создаваемого пользователя (в нашем примере это имя хранится в переменной strUser ):

Set objUser = objComputer.Create("user",strUser)

Замечание

Для создания пользователя или группы у вас в системе должны быть назначены права, которыми обладает администратор.

Для созданного пользователя в свойство Description мы помещаем текст описания:

UserObj.Description="Этот пользователь создан из сценария ADSI"

Для сохранения информации о новом пользователе в базе данных пользователей вызывается метод SetInfo объекта User.

'********************************************************************
' Имя: AddUser.vbs                                                  
' Язык: VBScript                                                    
' Описание: Создание нового пользователя компьютера                
'********************************************************************
Option Explicit

'Объявляем переменные
Dim objComputer        ' Экземпляр объекта Computer
Dim objUser            ' Экземпляр объекта User
Dim strUser            ' Имя создаваемого пользователя

' Задаем имя пользователя
strUser = "XUser"
' Связываемся с компьютером Popov
Set objComputer = GetObject("WinNT://Popov")
' Создаем объект класса User
Set objUser = objComputer.Create("user",strUser)
' Добавляем описание созданного пользователя
objUser.Description = "Этот пользователь создан из сценария ADSI"

' Сохраняем информацию на компьютере
objUser.SetInfo
'*************  Конец *********************************************
Листинг 8.2. Создание нового локального пользователя на рабочей станции (html, txt)

Группа на рабочей станции создается аналогичным образом (листинг 8.3).

'********************************************************************
' Имя: AddGroup.vbs                                                  
' Язык: VBScript                                                    
' Описание: Создание новой группы на компьютере
'********************************************************************
Option Explicit

'Объявляем переменные
Dim objComputer        ' Экземпляр объекта Computer
Dim objGroup           ' Экземпляр объекта Group
Dim strGroup           ' Имя создаваемой группы

' Задаем имя пользователя
strGroup = "XGroup"
' Связываемся с компьютером Popov
Set objComputer = GetObject("WinNT://Popov")
' Создаем объект класса Group
Set objGroup = objComputer.Create("group",strGroup)
' Сохраняем информацию на компьютере
objGroup.SetInfo
'*************  Конец *********************************************
Листинг 8.3. Создание новой локальной группы на рабочей станции (html, txt)

Вывод информации о пользователе и смена его пароля

В листинге 8.4 приведен сценарий UserInfo.vbs, в котором выводится на экран информация о созданном в сценарии AddUser.vbs пользователе XUser. Для получения этой информации мы производим связывание с нужным пользователем, т.е. создаем экземпляр objUser объекта User и читаем данные из полей этого объекта:

' Связываемся с пользователем XUser компьютера Popov
Set objUser = GetObject("WinNT://Popov/XUser,user")
' Формируем строку с информацией о пользователе
strResult = "Информация о пользователе XUser" & vbCrLf &_
        "Имя: " & objUser.Name & vbCrLf & _
        "Описание: " & objUser.Description & vbCrLf
' Выводим сформированную строку на экран
WScript.Echo strResult

После этого в сценарии выдается запрос на изменение пароля пользователя XUser. Для этого мы используем метод Popup() объекта WshShell:

' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
' Запрос на изменение пароля
Res = WshShell.Popup("Изменить пароль у XUser?",0,_
  "Администрирование пользователей",vbQuestion+vbYesNo)

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

If Res=vbYes Then ' Нажата кнопка Да
  ' Устанавливаем новый пароль
  objUser.SetPassword "NewPassword"
  ' Сохраняем сделанные изменения
  objUser.SetInfo
'********************************************************************
' Имя: UserInfo.vbs                                                 
' Язык: VBScript                                                    
' Описание: Вывод информации о пользователе компьютера и смена     
'           его пароля                                             
'********************************************************************
Option Explicit

'Объявляем переменные
Dim objUser      ' Экземпляр объекта User
Dim WshShell     ' Объект WshShell
Dim Res          ' Результат нажатия кнопки в диалоговом окне
Dim strPassword  ' Строка с новым паролем
Dim strResult    ' Строка для вывода на экран

'********************** Начало *************************************
' Связываемся с пользователем XUser компьютера Popov
Set objUser = GetObject("WinNT://Popov/XUser,user")
' Формируем строку с информацией о пользователе
strResult = "Информация о пользователе XUser" & vbCrLf &_
        "Имя: " & objUser.Name & vbCrLf & _
        "Описание: " & objUser.Description & vbCrLf
' Выводим сформированную строку на экран
WScript.Echo strResult

' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
' Запрос на изменение пароля
Res = WshShell.Popup("Изменить пароль у XUser?",0,_
  "Администрирование пользователей",vbQuestion+vbYesNo)
If Res=vbYes Then ' Нажата кнопка Да
  ' Устанавливаем новый пароль
  objUser.SetPassword "NewPassword"
  ' Сохраняем сделанные изменения
  objUser.SetInfo
  WScript.Echo "Пароль был изменен"
Else
  WScript.Echo "Вы отказались от изменения пароля"
End If  
'*************  Конец *********************************************/
Листинг 8.4. Вывод информации о пользователе компьютера и смена его пароля (html, txt)

Удаление пользователя и группы на рабочей станции

Для удаления созданных с помощью сценариев AddUser.vbs и AddGroup.vbs пользователя XUser и группы XGroup, мы создадим сценарий DelUserAndGroup.vbs, который представлен в листинге 8.5.

Замечание

Для удаления пользователя или группы у вас в системе должны быть назначены права, которыми обладает администратор.

В принципе, удалить пользователя и группу так же просто, как и создать — нужно связаться с объектом Computer:

Set objComputer = GetObject("WinNT://Popov")

и вызвать метод Delete, указав в качестве первого параметра класс объекта, который мы хотим удалить, и в качестве второго параметра — имя этого объекта:

' Удаляем пользователя

objComputer.Delete "user", strUser

Однако здесь могут возникнуть ошибки (например, мы не запускали предварительно сценарий AddUser.vbs и у нас на компьютере не зарегистрирован пользователь, которого мы хотим удалить). Поэтому в сценарии DelUserAndGroup.vbs предусмотрена обработка исключительных ситуаций с помощью стандартного объекта Err:

If Err.Number <> 0 Then  
  strMess="Ошибка при удалении пользователя " & strUser & vbCrLf & _
       "Код ошибки: " & Err.number & "Описание: " & Err.description
  WshShell.Popup strMess,0,"Удаление пользователя",vbCritical

  ' Очищаем свойства объекта Err
  Err.Clear
Else
  ' Все в порядке
  strMess = "Пользователь " & strUser & " удален"
  WshShell.Popup strMess,0,"Удаление пользователя",vbInformation
End If

Как мы видим, если при вызове метода Delete произойдет какая-либо ошибка, то на экран с помощью метода Popup объекта WshShell выведется соответствующее сообщение. Если же удаление прошло успешно (свойство Number объекта Err равно нулю), то на экран также выведется соответствующее диалоговое окно.

Процесс удаления группы в сценарии проходит аналогично.

'********************************************************************
' Имя: DelUserAndGroup.vbs  
' Язык: VBScript                                                    
' Описание: Удаление пользователя и группы компьютера
'********************************************************************
Option Explicit
On Error Resume Next

'Объявляем переменные
Dim objComputer          ' Экземпляр объекта Computer
Dim strUser              ' Имя удаляемого пользователя
Dim strGroup             ' Имя удаляемой группы
Dim WshShell             ' Объект WshShell
Dim strMess              Строка для вывода на экран

'********************** Начало *************************************
' Имя удаляемого пользователя
strUser = "XUser"    
' Имя удаляемой группы
strGroup = "XGroup"  

' Связываемся с компьютером Popov
Set objComputer = GetObject("WinNT://Popov")
' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")

'*************  Удаление пользователя  ***********************
' Удаляем пользователя
objComputer.Delete "user", strUser

' Обрабатываем ошибки
If Err.Number <> 0 Then  
  strMess="Ошибка при удалении пользователя " & strUser & vbCrLf & _
       "Код ошибки: " & Err.number & "Описание: " & Err.description
  WshShell.Popup strMess,0,"Удаление пользователя",vbCritical

  ' Очищаем свойства объекта Err
  Err.Clear
Else
  ' Все в порядке
  strMess = "Пользователь " & strUser & " удален"
  WshShell.Popup strMess,0,"Удаление пользователя",vbInformation
End If

'*************  Удаление группы  ***********************/
objComputer.Delete "group", strGroup

' Обрабатываем ошибки
If Err.Number <> 0 Then  
  strMess="Ошибка при удалении группы " & strGroup & vbCrLf & _
       "Код ошибки: " & Err.number & "Описание: " & Err.description
  ' Очищаем свойства объекта Err
  Err.Clear
Else
  ' Все в порядке
  strMess="Группа " & strGroup & " удалена"
  WshShell.Popup strMess,0,"Удаление группы",vbInformation
End If
'*************  Конец *********************************************/
Листинг 8.5. Удаление пользователя и группы на рабочей станции (html, txt)

Список всех групп на рабочей станции

Принцип формирования списка всех групп рабочей станции остается тем же, что и для рассмотренного выше списка всех доступных доменов локальной сети, однако первоначальное связывание нужно производить не с корневым объектом класса Namespace, а с нужным объектом класса Computer.

В приведенном в листинге 8.6 сценарии ListAllGroups.vbs для связывания с компьютером Popov мы создаем объект-контейнер objComputer, в котором содержатся все объекты рабочей станции Popov:

Set objComputer = GetObject("WinNT://Popov")

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

strResult = "На компьютере Popov созданы группы:" & vbCrLf  & vbCrLf

После этого в цикле For Each … In … из коллеции objComputer выбираются лишь объекты класса Group, то есть те объекты, у которых в поле Class записана строка "Group"; в strResult заносятся названия групп из поля Name:

For Each objGroup In objComputer
  ' Выделяем объекты класса Group
  If objGroup.Class = "Group" Then
    'Формируем строку с именами групп
    strResult = strResult & objGroup.Name & vbCrLf
  End If
Next

После окончания цикла сформированная строка выводится на экран.

'********************************************************************
' Имя: ListAllGroups.vbs
' Описание: Вывод на экран имен всех групп заданного компьютера 
'********************************************************************
Option Explicit

'Объявляем переменные
Dim objComputer    ' Экземпляр объекта Computer
Dim objGroup       ' Экземпляр объекта Group
Dim strResult      ' Строка для вывода на экран

'********************** Начало *************************************
' Связываемся с компьютером Popov
Set objComputer = GetObject("WinNT://Popov")

strResult = "На компьютере Popov созданы группы:" & vbCrLf  & vbCrLf

' Перебираем элементы коллекции 
For Each objGroup In objComputer
  ' Выделяем объекты класса Group
  If objGroup.Class = "Group" Then
    'Формируем строку с именами групп
    strResult = strResult & objGroup.Name & vbCrLf
  End If
Next
    
'Выводим информацию на экран
WScript.Echo strResult
'*************  Конец *********************************************/
Листинг 8.6. Вывод на экран имен всех локальных групп заданной рабочей станции (html, txt)

Список всех пользователей в группе

В листинге 8.7 приведен сценарий ListUsers.vbs, в котором формируется список всех пользователей, входящих в группу "Пользователи" на компьютере Popov.

Для связывания с группой "Пользователи" рабочей станции Popov создается объект objGroup ; коллекция пользователей этой группы формируется с помощью метода Members объекта Group:

Set objGroup = GetObject("WinNT://Popov/Пользователи,group")

После инициализации переменной strResult мы обрабатываем в цикле For Each … In … все элементы полученной коллекции пользователей группы (данная коллекция формируется с помощью метода Members объекта Group ); на каждом шаге цикла к переменной strResult добавляется имя текущего пользователя (поле Name в объекте objUser — текущем элементе коллекции):

strResult = "Все пользователи группы Пользователи 
 на компьютере Popov:" & vbCrLf
' Перебираем элементы коллекции 
For Each objUser In objGroup.Members()
  ' Формируем строку с именами пользователей
  strResult = strResult & objUser.Name & vbCrLf
Next

После выхода из цикла сформированная строка strResult выводится на экран.

'********************************************************************
' Имя: ListUsers.vbs                                                
' Язык: VBScript                                    
' Описание: Вывод на экран имен всех пользователей заданной группы
'********************************************************************
Option Explicit

'Объявляем переменные
Dim objGroup       ' Экземпляр объекта Group
Dim objUser        ' Экземпляр объекта User
Dim strResult      ' Строка для вывода на экран

'********************** Начало *************************************
' Связываемся с группой Пользователи компьютера Popov
Set objGroup = GetObject("WinNT://Popov/Пользователи,group")

strResult = "Все пользователи группы Пользователи на компьютере Popov:" & vbCrLf

' Перебираем элементы коллекции 
For Each objUser In objGroup.Members()
  ' Формируем строку с именами пользователей
  strResult = strResult & objUser.Name & vbCrLf
Next

' Вывод информации на экран
WScript.Echo strResult
'*************  Конец *********************************************
Листинг 8.7. Вывод на экран имен всех пользователей заданной группы (html, txt)

Лекция 9. Сценарии WSH как XML-документы. Схема WS XML

Описывается XML-формат сценариев WSH (схема WS XML). Обсуждаются возможности подключения внешних файлов сценариев, использования в одном сценарии нескольких языков и доступа к константам внешних COM-объектов. Даются примеры сценариев WSH с разметкой XML

Сценарии WSH как XML-документы. Схема WS XML

До сих пор мы рассматривали простые одиночные файлы сценариев, в которых мог использоваться язык JScript или VBScript. В версии WSH 1.0 это был единственный поддерживаемый тип сценариев, причем используемый язык определялся по расширению файла: js для JScript и vbs для VBScript. Начиная с WSH 2.0 появилась возможность создавать сценарии, в которых можно применять оба языка одновременно. Для таких сценариев в операционной системе регистрируется расширение wsf; wsf-файлы мы будем далее называть просто WS-файлами. Новый тип сценариев (WS-файл) имеет еще несколько важных преимуществ перед одиночными файлами сценариев WSH 1.0:

Понятно, что для обеспечения новых возможностей необходимо иметь больше информации, чем ее может предоставить отдельный сценарий. В самом файле сценария должна присутствовать некоторая дополнительная информация, скажем, имя этого сценария (подобная информация содержится, например, в заголовках HTML-страниц). Другими словами, для сценариев WSH должен использоваться уже некий специальный формат, а не просто отдельные js- или vbs-файлы. В качестве такого формата разработчики Microsoft выбрали язык XML (Extensible Markup Language), который уже использовался ими для определения информационной модели в технологии Windows Script Components (WSC), которая позволяет с помощью языков сценариев создавать и регистрировать полноценные COM-объекты.

Таким образом, теперь сценарии WSH не просто содержат в текстовом виде ActiveX-совместимый сценарий, а являются XML-приложениями, поддерживающими схему WS XML (Windows Script XML), которая, в свою очередь, опирается на схему WSC XML. Поэтому для понимания двух технологий (WSC и WSH) достаточно освоить одну схему XML.

WS-файл рассматривается сервером сценариев как файл с разметкой XML, который должен соответствовать схеме WS XML. Новый тип файла и формат XML обеспечивают более мощную среду для написания сценариев.

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

Основные принципы XML

Проявляемый в настоящее время большой интерес к языку XML объясняется тем, что он предоставляет возможности, позволяющие в текстовой форме описывать структурированные данные. Точнее говоря, XML является метаязыком для создания различных языков разметки, которые способны определять произвольные структуры данных — двоичные данные, записи в базе данных или сценарии. Прежде всего, XML используется в Internet-приложениях при работе браузеров, которые отображают информацию, находящуюся на Web-серверах. При этом пользователю отдельно передаются данные в виде XML-документа, и отдельно — правила интерпретации этих данных для отображения с помощью, например, языков сценариев JScript или VBScript.

Как и HTML, XML является независимым от платформы промышленным стандартом. Полные спецификации XML и связанных с ним языков доступны на официальной странице корпорации World Wide Web Consortium (W3C) по адресу http://www.w3c.org/xml.

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

Рассмотрим теперь структуру и синтаксис WS-файлов, использующих схему WS XML.

Схема WS XML

Синтаксис элементов, составляющих структуру WS-файла, в общем виде можно представить следующим образом:

<element [attribute1="value1" [attribute2="value2" ... ]]>
   Содержимое (content)
</element>

Открывающий тег элемента состоит из следующих компонентов:

Например, тег начала элемента

<script language="JScript">

имеет имя тега script и определяет атрибут language со значением "JScript". Атрибуты предоставляют дополнительную информацию о соответствующем теге или последующем содержимом элемента. В нашем примере атрибут указывает на то, что содержимым элемента является текст сценария на языке JScript.

Закрывающий тег элемента состоит из следующих компонентов:

Таким образом, тег конца элемента не имеет атрибутов, например, </script>.

Если у элемента нет содержимого, то он имеет следующий вид:

<element [attribute1="value1" [attribute2="value2" … ]]/>

То есть в этом случае элемент состоит из следующих компонентов:

Пример такого элемента:

<script language="JScript" src="tools.js"/>

Представленная в табл. 9.1 схема WS XML — это модель данных, определяющая элементы и соответствующие атрибуты, а также связи элементов друг с другом и возможную последовательность появления элементов. Также эта схема может задавать значения атрибутов по умолчанию.

Таблица 9.1. Схема WS XML
<?XML version="1.0" standalone="yes"?>
<package>
<job [id="JobID"]>
<?job debug="true|false"?>
<runtime>
<named name="NamedName" helpstring="HelpString" type="string|boolean|simple" required="true|false" />
<unnamed name="UnnamedName" helpstring="HelpString" many="true|false" required="true|false" />
<description> Описание сценария </description>
<example> Пример запуска сценария </example>
</runtime>
<resource id="ResourceID"> Строка или число </resource>
<object id="ObjID" [classId="clsid:GUID"|progid="ProgID"]/>
<reference [object="ProgID"|guid="typelibGUID"][version="version"]/>
<script language="language" [src="strFileURL"]\>
<script language="language" >
<![CDATA[
Код сценария
]]>
</script>
</job>
Другие задания
</package>

Таким образом, из табл. 9.1 видно, что:

Обязательными для создания корректного сценария являются только элементы <job> и <script>. Сам код сценария всегда располагается внутри элемента <script>.

Опишем теперь элементы XML, использующие в сценариях WSH, более подробно.

Элементы WS-файла

В WS-файл можно вставлять комментарии независимо от разметки XML. Сделать это можно двумя способами: с помощью элемента <!-- --> или элемента <comment>. Например:

<!-- Первый комментарий -->

или

<comment>
Второй комментарий
</comment>
Элементы <?XML?> и <![CDATA[]]>

Эти элементы являются стандартными для разметки W3C XML 1.0. В сценариях WSH они определяют способ обработки WS-файла. Всего существует два режима обработки сценария: нестрогий (loose) и строгий (strict).

При нестрогой обработке (элемент <?XML?> отсутствует) не предполагается выполнение всех требований стандарта XML. Например, не требуется различать строчные и заглавные буквы и заключать значения атрибутов в двойные кавычки. Кроме этого, в процессе нестрогой обработки считается, что все содержимое между тегами <script> и </script> является исходным кодом сценария. Однако при таком подходе может произойти ошибочная интерпретация вложенных в сценарий зарезервированных для XML символов или слов как разметки XML. Например, имеющиеся в коде сценария знаки "меньше" (<) и "больше" (>) могут привести к прекращению разбора и выполнения сценария.

Для того чтобы задать режим строгой обработки сценария, нужно поместить элемент <?XML?> в самой первой строке сценария — никаких других символов или пустых строк перед ним быть не должно. При такой обработке WS-файла нужно четко следовать всем правилам стандарта XML. Код сценария должен быть помещен в секцию CDATA, которая начинается с символов "<![CDATA[" и заканчивается символами "]]>".

Элемент <?job?>

Элемент <?job?> задает режим отладки при выполнении WS-файла. Если значение атрибута debug равно true, то задание может быть выполнено во внешнем отладчике. Если же значение атрибута debug равно false, то отладчик для этого задания применен быть не может. По умолчанию debug имеет значение false.

Элемент <package>

Этот элемент необходим в тех WS-файлах, в которых с помощью элементов <job> определено более одного задания. В этом случае все эти задания должны находиться внутри пары тегов <package> и </package> (см. табл. 3.1). Другими словами, <package> является контейнером для элементов <job>.

Если же в WS-файле определено только одно задание, то элемент <package> можно не использовать.

Элемент <job>

Элементы <job> позволяют определять несколько заданий (независимо выполняющихся частей) в одном WS-файле. Иначе говоря, между тегами <job> и </job> будет находиться отдельный сценарий (который, в свою очередь, может состоять из нескольких частей, написанных, возможно, на разных языках).

У элемента <job> имеется единственный атрибут id, который определяет уникальное имя задания. Например, в сценарии two_jobs.wsf определяются два задания с именами "Task1" и "Task2" (листинг 9.1).

<package>
<job id="Task1">
<!-- Описываем первое задание (id="Task1") -->
<script language="VBScript">
   WScript.Echo "Выполняется первое задание (VBScript)"
</script>
</job>
<job id="Task2">
<!-- Описываем второе задание (id="Task1") -->
<script language="JScript">
   WScript.Echo("Выполняется второе задание (JScript)");
</script>
</job>
</package>
Листинг 9.1. Файл two_jobs.wsf (html, txt)

Для того чтобы запустить конкретное задание из многозадачного WS-файла, нужно воспользоваться параметром //job:"JobID" в командной строке WSH. Например, следующая команда:

cscript //job:"Task1" two_jobs.wsf

запускает с помощью cscript.exe задание с именем "Task1" из файла two_jobs.wsf.

Замечание

Если параметр //job не указан, то по умолчанию из многозадачного WS-файла запускается первое задание.

Если в WS-файле имеется несколько заданий, то они должны находиться внутри элемента <package>. Элемент <job> является одним из двух обязательных элементов в сценариях WSH с разметкой XML.

Элемент <runtime>

При запуске почти всех стандартных команд или утилит командной строки Windows с ключом /? на экран выводится встроенная справка, в которой кратко описываются назначение и синтаксис этой команды или утилиты. Хорошим тоном считается создание такой справки и для разрабатываемых сценариев WSH. Понятно, что добавление в сценарий функции вывода информации о назначении, синтаксисе и аргументах этого сценария потребовало бы написания довольно большого количества кода: необходимо следить за ключом /? в командной строке, а при добавлении нового параметра командной строки возникнет необходимость изменения функции, отвечающей за вывод информации на экран.

Элемент <runtime> позволяет сделать сценарий самодокументируемым, т. е. в этом случае при задании в командной строке ключа /? на экран будет автоматически выводиться информация об использовании сценария, о его синтаксисе и аргументах (именных и безымянных), а также пример запуска сценария с конкретными значениями аргументов.

При этом сам элемент <runtime> является лишь контейнером, а содержимое для вывода информации хранится в элементах <named> (описание именных параметров командной строки), <unnamed> (описание безымянных параметров командной строки), <description> (описание самого сценария) и <example> (пример запуска сценария), которые находятся внутри <runtime>.

Элемент <named>

С помощью элементов <named> можно описывать (документировать) именные параметры командной строки сценария. В табл. 9.2 приведено описание аргументов элемента <named>.

Таблица 9.2. Аргументы элемента <named>
АргументОписание
nameЗадает имя параметра командной строки
helpstringСтрока, содержащая описание параметра командной строки
typeОпределяет тип параметра командной строки. Может принимать значения "string" (символьный тип), "boolean" (логический тип), "simple" (в сценарий передается только имя параметра без дополнительного значения). По умолчанию используется тип "simple"
requiredИспользуется для того, чтобы показать, является ли параметр командной строки обязательным. Может принимать значения "true" (параметр нужно указывать обязательно) и "false" (параметр можно не указывать)

Информация, которая указывается для объявляемого в элементе <named> параметра командной строки, используется только для самодокументируемости сценария и никак не влияет на реальные значения, которые будут указаны в командной строке при запуске сценария. Например, если параметр объявлен как обязательный ( required="true" ), но в действительности не был указан при запуске сценария, то никакой ошибки во время работы не произойдет.

Если для аргумента командной строки сценария указан тип "string", то предполагается, что этот аргумент имеет имя и значение, разделенные символом ":", например:

/Имя:"Андрей  Попов"  /Возраст:33

Если в качестве типа параметра командной строки используется "simple", то для этого параметра в командной строке указывается только его имя без значения:

/Имя   /Возраст

Для того чтобы передать в сценарий аргумент командной строки типа "boolean", нужно после имени этого аргумента указать символ + (соответствует логическому значению "истина" ) или — (соответствует значению "ложь" ). Например:

/Запись+   /ReWrite–

В листинге 9.2 приведен сценарий named.wsf, в котором в блоке <runtime> описываются три именных аргумента командной строки:

После запуска с помощью wscript.exe в сценарии named.wsf сначала вызывается метод WScript.Arguments.Usage, в результате чего на экран выводится диалоговое окно с информацией о сценарии и параметрах командной строки. Затем в сценарии проверяется, какие именно аргументы командной строки были подставлены при запуске и выделяются значения этих аргументов. Для этого создается объект WshNamed, являющийся коллекцией именных аргументов командной строки, и используется метод Exists этого объекта.

Значением параметра /Новый является константа логического типа ( true или false ), поэтому для формирования строки, соответствующей этому значению, используется условный оператор языка JScript:

//Проверяем, существует ли аргумент /Новый
if (objNamedArgs.Exists("Новый"))
  //Получаем с помощью условного оператора значение
  //логического аргумента /Новый
  s+="Новый пользователь: "+(objNamedArgs("Новый") ? "Да" : "Нет");
<job id="Named">
<runtime>
<description>
Имя: named.wsf
</description>
<named
   name="Имя"
   helpstring="Имя пользователя"
   type="string"
   required="true"
/>
<named
   name="Компьютер"
   helpstring="Имя рабочей станции"
   type="string"
   required="false"
/>
<named
   name="Новый"
   helpstring="Признак того, что такого пользователя раньше не было"
   type="boolean"
   required="true"
/>
</runtime>

<script language="JScript">
var objNamedArgs,s;
//Вызываем метод ShowUsage для вывода на экран описания сценария
WScript.Arguments.ShowUsage();
//Создаем объект WshNamed — коллекция именных аргументов сценария
objNamedArgs= WScript.Arguments.Named;
s="";
//Проверяем, существует ли аргумент /Имя:
if (objNamedArgs.Exists("Имя"))
  //Получаем значение символьного аргумента /Имя
  s+="Имя: "+objNamedArgs("Имя")+"\n";
//Проверяем, существует ли аргумент /Компьютер:
if (objNamedArgs.Exists("Компьютер"))
  //Получаем значение символьного аргумента /Компьютер
  s+="Машина: "+objNamedArgs("Компьютер")+"\n";
//Проверяем, существует ли аргумент /Новый
if (objNamedArgs.Exists("Новый"))
  //Получаем с помощью условного оператора значение
  //логического аргумента /Новый
  s+="Новый пользователь: "+(objNamedArgs("Новый") ? "Да" : "Нет");
//Выводим полученные строки на экран
WScript.Echo(s);
</script>
</job>
Листинг 9.2. Файл named.wsf (html, txt)
Элемент <unnamed>

С помощью элементов <unnamed> можно описывать (документировать) безымянные параметры командной строки сценария. В табл. 9.3 приведено описание аргументов элемента <unnamed>.

Таблица 9.3. Аргументы элемента <unnamed>
АргументОписание
nameЗадает имя, которое будет указано для описываемого параметра командной строки при выводе информации о сценарии
helpstringСтрока, содержащая описание параметра командной строки
manyОпределяет, сколько раз может быть указан безымянный параметр в командной строке. Значение, равное "true" (используется по умолчанию), означает, что безымянный параметр может встретиться в командной строке более одного раза. Значение, равное "false", означает, что безымянный параметр должен быть указан только один раз
requiredОпределяет, является ли безымянный параметр командной строки обязательным. Может принимать значения "true", "on" или 1 (параметр нужно указывать обязательно), "false", "off" или 0 (параметр можно не указывать). Также значением аргумента "required" может быть целое число, которое показывает, сколько раз безымянный параметр должен обязательно быть указан в командной строке

Информация, которая указывается для объявляемого в элементе <unnamed> параметра командной строки, используется, как и в случае элемента <named>, только для самодокументируемости сценария и никак не влияет на реальные значения, которые будут указаны в командной строке при запуске сценария. Например, если безымянный параметр объявлен как обязательный ( required="true" ), но в действительности не был указан при запуске сценария, то никакой ошибки во время работы не произойдет.

Рассмотрим в качестве примера сценарий unnamed.wsf, в который в качестве параметров командной строки должны передаваться расширения файлов, причем обязательно должны быть указаны хотя бы два таких расширения (листинг 9.3).

Для создания информации об использовании этого сценарии создается элемент <unnamed> следующего вида:

<unnamed
   name="Расш"
   helpstring="Расширения файлов"
   many="true"
   required=2
/>

После запуска с помощью wscript.exe в сценарии unnamed.wsf сначала вызывается метод WScript.Arguments.Usage, в результате чего на экран выводится диалоговое окно с информацией о сценарии и параметрах командной строки. Затем в сценарии создается коллекция objUnnamedArgs (объект WshUnnamed ), которая содержит все безымянные аргументы командной строки, реально переданные в сценарий:

objUnnamedArgs=WScript.Arguments.Unnamed;  //Создаем объект WshUnnamed

После этого определяется общее число реально переданных в сценарий параметров командной строки (свойство length ) и в цикле while организуется перебор всех элементов коллекции objUnnamedArgs.

<job id="Unnamed">
<runtime>
<description>
Имя: unnamed.wsf
</description>
<unnamed
   name="Расш"
   helpstring="Расширения файлов"
   many="true"
   required=2
/>
</runtime>

<script language="JScript">
var objUnnamedArgs,s;
//Вызываем метод ShowUsage для вывода на экран описания сценария
WScript.Arguments.ShowUsage();
objUnnamedArgs=WScript.Arguments.Unnamed;  //Создаем объект WshUnnamed
//Определяем количество безымянных аргументов
s="Передано в сценарий безымянных аргументов: "+objUnnamedArgs.length;
for (i=0; i<=objUnnamedArgs.length-1; i++)
  //Формируем строки со значениями безымянных аргументов
  s+="\n"+objUnnamedArgs(i);
//Выводим полученные строки на экран
WScript.Echo(s);
</script>
</job>
Листинг 9.3. Файл unnamed.wsf (html, txt)
Элемент <description>

Внутри элемента <description> помещается текст (без дополнительных кавычек), описывающий назначение сценария. Как и все элементы внутри <runtime>, этот текст выводится на экран, если сценарий был запущен с ключом /? в командной строке или если в сценарии встретился вызов метода ShowUsage объекта WshArguments. При выводе текста на экран учитываются все имеющиеся в нем пробелы, символы табуляции и перевода строки.

Пример использования элемента <description> и метода ShowUsage представлен в сценарии descrip.wsf (листинг 9.4). Здесь сразу вызывается метод WScript.Arguments.ShowUsage, в результате чего на экран выводится диалоговое окно (в случае запуска сценария с помощью wscript.exe) или просто строки текста (в случае запуска сценария с помощью cscript.exe) с описанием запущенного сценария.

<job id="Descrip">
<runtime>
<description>
Имя: descrip.wsf
Описание: Здесь можно привести дополнительное описание сценария
</description>
</runtime>
<script language="JScript">
//Вызываем метод ShowUsage
WScript.Arguments.ShowUsage();
</script>
</job>
Листинг 9.4. Файл descrip.wsf (html, txt)
Элемент <example>

Внутри элемента <example> приводится текст из одной или нескольких строк, в котором можно описать примеры запуска сценария. Если сценарий был запущен с ключом /? в командной строке или в сценарии встретился вызов метода ShowUsage объекта WshArguments, то этот текст выводится в графическое диалоговое окно (при использовании wscript.exe) или на экран (в консольном режиме при использовании cscript.exe). При выводе текста на экран учитываются все имеющиеся в нем пробелы, символы табуляции и перевода строки, при этом строки из элемента <example> выводятся после строк из элемента <description>.

Пример использования элемента <example> приведен в листинге 9.5.

<job id="Example">
<runtime>
<description>
Имя: example.wsf
Описание: Здесь можно привести дополнительное описание сценария
</description>
<example>
 
Здесь приводится пример запуска сценария
(с параметрами командной строки, например)
</example>
</runtime>
<script language="JScript">
//Вызываем метод ShowUsage
WScript.Arguments.ShowUsage();
</script>
</job>
Листинг 9.5. Файл example.wsf (html, txt)
Элемент <resource>

Элемент <resource> позволяет отделить символьные или числовые константы (ресурсы) от остального кода сценария. Например, таким образом удобно собрать в одном месте строки, которые используются в сценарии для вывода каких-либо стандартных сообщений. Если после этого понадобится изменить сообщения в сценарии (например, перевести их на другой язык), то достаточно будет внести соответствующие корректировки в строки, описанные в элементах <resource>.

Для получения значения ресурса в сценарии нужно вызвать метод getResource, передав в качестве параметра символьный идентификатор ресурса (значение атрибута id).

В листинге 9.6 представлен пример сценария resource.wsf, в котором определяется ресурсная строка с идентификатором "MyName":

<resource id="MyName">
Меня зовут Андрей Попов
</resource>

Значение этого ресурса затем выводится на экран с помощью метода Echo объекта WScript и метода getResource:

WScript.Echo(getResource("MyName"));
<job id="Resource">
<runtime>
<description>
Имя: resource.wsf
Описание: Пример использования в сценарии ресурсных строк
</description>
</runtime>
<resource id="MyName">
Меня зовут Андрей Попов
</resource>
<script language="JScript">
//Выводим на экран значение ресурса "MyName"
WScript.Echo(getResource("MyName"));
</script>
</job>
Листинг 9.6. Файл resource.wsf (html, txt)
Элемент <object>

Элемент <object> предлагает еще один способ создания экземпляра COM-объектов для использования их внутри сценариев. Напомним, что ранее для этого мы использовали методы CreateObject и GetObject объекта WScript, объект ActiveXObject и функцию GetObject языка JScript, а также функцию CreateObject языка VBScript. Элемент <object> может заменить эти средства.

Атрибут id в <object> — это имя, применяемое для обращения к объекту внутри сценария. Отметим, что объект, создаваемый с помощью тега <object>, будет глобальным по отношению к тому заданию, в котором он определен. Другими словами, этот объект может использоваться во всех элементах <script>, находящихся внутри элемента <job>, содержащего описание объекта.

Атрибуты classid и progid используются в <object> соответственно для указания глобального кода создаваемого объекта (Globally Unique ID, GUID) или программного кода объекта (Programmic Identifier). Из этих двух необязательных атрибутов может быть указан только один. Например, создать объект FileSystemObject (GUID="0D43FE01-F093-11CF-8940-00A0C9054228") можно двумя способами:

<object id="fso" classid="clsid:0D43FE01-F093-11CF-8940-00A0C9054228"/>

или

<object id="fso" progid="Scripting.FileSystemObject"/>

В обычном js-файле или внутри элемента <script> этот объект мы бы создали следующим образом:

var fso = WScript.CreateObject("Scripting.FileSystemObject");

или

var fso = new ActiveXObject("Scripting.FileSystemObject");
Элемент <reference>

При вызове многих методов внешних объектов, которые используются внутри сценариев, требуется указывать различные числовые или строковые константы, определенные в этих внешних объектах. Например, для того, чтобы открыть текстовый файл с помощью метода OpenTextFile объекта FileSystemObject, может потребоваться указать параметр, который определяет режим ввода/вывода (возможные значения констант ForReading=1, ForWriting=2 и ForAppending=8 ) открываемого файла. Ясно, что запомнить все значения констант различных объектов очень трудно, поэтому при их использовании приходится постоянно обращаться к справочной информации.

К счастью, большинство объектов предоставляет информацию об именах используемых ими констант в своей библиотеке типов, которая регистрируется в системном реестре при установке COM-объекта и может существовать как в виде отдельного файла с расширением tlb, так и в виде части файла с исполняемым кодом объекта. Элемент <reference> как раз обеспечивает доступ к мнемоническим константам, определенным в библиотеке типов объекта (экземпляр объекта при этом не создается).

Для того чтобы воспользоваться константами определенного объекта, нужно в теге <reference> указать программный код этого объекта (атрибут object ) или глобальный код его библиотеки типов (атрибут guid ), а также, при необходимости, номер версии объекта (атрибут version ).

Например, доступ к константам объекта FileSystemObject организуется следующим образом:

<reference object="Scripting.FileSystemObject"/>

После этого в сценариях можно просто использовать константы с именами ForReading или ForAppending, не заботясь об их числовых значениях.

Элемент <script>

Элемент <script> с помощью атрибута language позволяет определить язык сценария ( language="JScript" для языка JScript и language="VBScript" для языка VBScript). Это делает возможным использовать в одном задании сценарии, написанные на разных языках (мультиязычные сценарии), что иногда бывает очень удобно. Предположим, что у вас имеются сценарии на JScript и VBScript, функции которых необходимо объединить. Для этого не нужно переписывать один из сценариев на другой язык — используя WS-файл, можно из сценария JScript спокойно вызывать функции, написанные на VBScript и наоборот!

Атрибут src позволяет подключить к выполняющемуся сценарию внешний файл с другим сценарием. Например, задание элемента

<script language="JScript" src="tools.js"/>

приведет к такому же результату, как если бы содержимое файла tools.js было расположено между тегами <script> и </script>:

<script language="JScript">
   Содержимое файла tools.js
</script>

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

Примеры сценариев с разметкой XML

Приведем примеры сценариев, иллюстрирующие основные свойства WS-файлов.

Несколько заданий в одном файле

Каждое отдельное задание в WS-файле должно находиться внутри элементов <job> и </job>. В свою очередь, все элементы <job> являются дочерними элементами контейнера <package>.

В качестве примера рассмотрим сценарий multijob.wsf, приведенный в листинге 9.7. Здесь описываются два задания с идентификаторами "VBS" (сценарий на языке VBScript) и "JS" (сценарий на языке JScript).

<package>
<job id="VBS">
<!-- Описываем первое задание (id="VBS") -->
<runtime>
<description>
Имя: multijob.wsf
Описание: Первое задание из multijob.wsf
</description>
</runtime>
<script language="VBScript">
   WScript.Echo "Первое задание (VBScript)"
</script>
</job>
<job id="JS">
<!-- Описываем второе задание (id="JS") -->
<runtime>
<description>
Имя: multijob.wsf
Описание: Второе задание из multijob.wsf
</description>
</runtime>
<script language="JScript">
   WScript.Echo("Второе задание (JScript)");
</script>
</job>
</package>
Листинг 9.7. Файл multijob.wsf (html, txt)

Для того чтобы выполнить первое задание сценария multijob.wsf, которое выведет на экран строку "Первое задание (VBScript)", нужно выполнить одну из следующих команд:

cscript //job:"VBS" multijob.wsf
cscript multijob.wsf
wscript //job:"VBS" multijob.wsf
wscript multijob.wsf

Для запуска второго задания, выводящего на экран строку "Второе задание (JScript)", нужно явно указывать идентификатор этого задания, поэтому используется одна из двух команд:

cscript //job:"JS" multijob.wsf
wscript //job:"JS" multijob.wsf
Использование констант внешних объектов

Для того чтобы в сценарии обращаться по имени к константам, определенным во внешних объектах, не создавая экземпляров самих объектов, необходимо сначала получить ссылку на эти объекты с помощью элемента <reference>.

В листинге 9.8 приведен сценарий refer.wsf, в котором с помощью элемента <reference> производится доступ к трем константам объекта FileSystemObject ( ForReading, ForWriting и ForAppending ), которые определяют режим работы из сценария с внешним текстовым файлом. В результате выполнения сценария refer.wsf на экран выведется диалоговое окно с информацией о значениях констант объекта FileSystemObject.

<job id="Example">
<runtime>
<description>
Имя: refer.wsf
Описание: Использование констант внешних объектов
</description>
</runtime>
<!-- Получаем ссылку на объект FileSystemObject -->
<reference object="Scripting.FileSystemObject"/>
<script language="JScript">
var s;
  s="Значения констант объекта FileSystemObject:\n\n";
  //Получаем значение константы ForReading
  s+="ForReading="+ForReading+"\n";
  //Получаем значение константы ForWriting
  s+="ForWriting="+ForWriting+"\n";
  //Получаем значение константы ForAppending
  s+="ForAppending="+ForAppending;
  //Выводим полученные строки на экран
  WScript.Echo(s);
</script>
</job>
Листинг 9.8. Использование в сценарии констант внешних объектов (файл refer.wsf) (html, txt)
Подключение внешних файлов

К WS-файлу можно подключать "обычные" JScript- или VBScript-сценарии, которые находятся во внешних файлах. Для этого нужно указать путь к этому внешнему файлу в атрибуте src элемента <script>.

Для примера создадим файл inc.js, содержащий строку

WScript.Echo("Здесь выполняется сценарий inc.js");

и файл main.wsf, содержание которого приведено в листинге 9.9.

<job id="Example">
<runtime>
<description>
Имя: main.wsf
Описание: Подключение сценария, находящегося во внешнем файле
</description>
</runtime>
<!-- Подключаем сценарий из файла inc.js -->
<script language="JScript" src="inc.js"/>
<!-- Определяем основной сценарий -->
<script language="JScript">
  WScript.Echo("Здесь выполняется основной сценарий");
</script>
</job>
Листинг 9.9. Подключение внешнего сценария (файл main.wsf) (html, txt)

Если запустить main.wsf с помощью cscript.exe, то на экран выведутся две строки:

Здесь выполняется сценарий inc.js
Здесь выполняется основной сценарий
Различные языки внутри одного задания

Ни в WSH, ни в JScript нет метода или функции, которые позволяли бы в графическом режиме создать диалоговое окно для ввода текста. Однако в языке VBScript имеется функция InputBox, предназначенная как раз для этой цели; используя разметку XML, мы можем легко использовать эту функцию в сценариях JScript. Соответствующий пример приведен в сценарии multilang.wsf (листинг 9.10).

Сначала в этом сценарии на языке VBScript описывается функция InputName, которая возвращает строку, введенную с помощью функции InputBox:

<script language="VBScript">
  Function InputName
  InputName = InputBox("Введите Ваше имя:", "Окно ввода VBScript")
  End Function
</script>

Затем в следующем разделе <script> приводится JScript-сценарий, в котором происходит вызов функции InputName и сохранение возвращаемого ею значения в переменной s:

var s;
    s = InputName();

Значение полученной таким образом переменной s выводится затем на экран:

WScript.Echo("Здравствуйте, "+s+"!");
<job id="Example">
<runtime>
<description>
Имя: multilang.wsf
Описание: Использование функции InputBox в JScript-сценарии
</description>
</runtime>
<script language="VBScript">
  Function InputName  ' Описываем функцию на языке VBScript
  ' Вводим имя в диалоговом окне
  InputName = InputBox("Введите Ваше имя:", "Окно ввода VBScript")
  End Function
</script>
<script language="JScript">
    var s;
    s = InputName();  //Вызываем функцию InputName
    //Выводим значение переменной s на экран
    WScript.Echo("Здравствуйте, "+s+"!");
</script>
</job>
Листинг 9.10. пользование различных языков внутри одного задания (файл multilang.wsf) (html, txt)

Лекция 10. Информационная схема CIM. Объектная модель WMI

Обсуждаются основные концепции информационной схемы Common Information Model (CIM) и ее реализации Windows Management Instrumentation (WMI) для операционной системы Microsoft Windows. Описывается трехуровневая архитектура WMI. Затрагиваются вопросы безопасности при работе с WMI

Информационная схема CIM. Объектная модель WMI

Среди инструментов и средств автоматизации в операционной системе Windows особое место занимает технология Windows Management Instrumentation (WMI). Технология WMI — это созданная фирмой Microsoft реализация модели управления предприятием на базе Web (Web-Based Enterprise Management, WBEM), которая разработана и принята рабочей группой по управлению распределенными системами (Distributed Management Task Force, DMTF), при участии таких компаний, как BMC Software, Cisco Systems, Intel и Microsoft. Задачей WBEM была разработка таких стандартов для удаленного управления информационной средой предприятия, которые позволили бы управлять всеми физическими и логическими компонентами этой среды из одной точки и не зависели бы при этом от конкретного оборудования, сетевой инфраструктуры, операционной системы, файловой системы и т. д. Для этого была предложена схема CIM (Common Information Model), которая представляет физическую и логическую структуры компьютерной системы в виде единой расширяемой объектно-ориентированной информационной модели и определяет единые интерфейсы для получения информации о любом компоненте этой модели.

Назначение и возможности WMI

В ранних версиях Windows (до Windows 2000) для администрирования операционной системы приходилось пользоваться несколькими утилитами и инструментами, т. к. данные о компонентах системы хранились в различных источниках (база пользователей SAM, журнал событий Event Log, системный реестр и т. д.), доступ к которым осуществлялся с помощью разных утилит (диспетчер пользователей — User Manager, просмотрщик журнала событий — Event Log Viewer, редактор реестра — Regedit) и программных интерфейсов (Network API для работы с данными о пользователях, Event Log API для просмотра сведений о произошедших событиях, Registry API для чтения или редактирования системного реестра). Понятно, что это было неудобно, т. к. во-первых, приходилось осваивать множество не связанных друг с другом технологий и инструментов, а во-вторых, усложнялось взаимодействие разных компонентов компьютерной системы друг с другом (например, настройки в локальном реестре рабочей станции могли конфликтовать с политиками безопасности, заданными на сервере).

С появлением Windows 2000 эта ситуация была в основном исправлена. Появилась встроенная в операционную систему консоль управления MMC (Microsoft Management Console), с помощью которой можно из одной точки управлять большинством логических и физических компонентов компьютерной сети, построенной на основе Windows. В свою очередь, это стало возможным именно благодаря применению технологии WMI, которая, во-первых, делает доступ к информации о самых различных компонентах информационной системы (журнал событий, системный реестр, подсистема производительности, драйверы устройств и т. д.) независимым от типа этих компонентов, а во-вторых, осуществляет управление любой подсистемой стандартным, не зависящим от реализации этой подсистемы, методом.

Итак, технология WMI — это глобальная концепция настройки, управления и слежения за работой различных частей корпоративной компьютерной сети. В частности, используя WMI, можно с помощью специальных утилит или сценариев Windows Script Host (WSH) решать следующие задачи.

Общая структура WMI

Архитектура WMI состоит из трех частей, показанных на рис. 10.1:

Управляемые объекты/ресурсы (managed resources) — любые логические или физические компоненты информационной системы, доступ к которым может быть получен с помощью WMI. В качестве управляемых ресурсов могут выступать, например, файлы на жестком диске, запущенный экземпляр приложения, системное событие, предоставленный в общее пользование ресурс, сетевой пакет или установленный в компьютере процессор.

Ядро WMI (WMI infrastructure). Это связующее звено архитектуры WMI, отвечающее за связь управляющих программ с управляемыми объектами. Ядро WMI, в свою очередь, можно разделить на три части: менеджер объектов CIM (Common Information Model Object Manager, CIMOM), репозиторий (хранилище классов и объектов) CIM и провайдеры WMI. Кроме этого, для доступа к WMI с помощью сценариев необходима специальная библиотека поддержки сценариев WMI (WMI scripting library), которая располагается в файле wbemdisp.dll в каталоге %SystemRoot%\System32\Wbem.

Управляющие программы (management applications), которые являются потребителями сервисов WMI. В качестве потребителей могут выступать полновесные Win32-приложения, Web-приложения, сценарии WSH или другие инструменты администрирования, с помощью которых происходит доступ к управляемым объектам посредством WMI.

Архитектура WMI


Рис. 10.1.  Архитектура WMI

Отметим, что управляющие программы (потребители) различных типов применяют разные механизмы для доступа к WMI, т. е. используют разные интерфейсы прикладного программирования (Application Programming Interface, API). Программы Win32 могут взаимодействовать с WMI напрямую, используя для этого WMI COM API — главный API управления. ActiveX-компоненты WMI реализуют API другого уровня: разработчики Web-приложений применяют средства управления ActiveX для создания сетевых интерфейсов к данным WMI. Еще один способ управления WMI предполагает использование сценариев WSH с помощью специального API WMI для сценариев (такие сценарии мы иногда будем называть просто сценариями WMI).

Ядро WMI

Ядро WMI составляют провайдеры WMI, менеджер объектов CIM и репозиторий CIM. Рассмотрим эти компоненты более подробно.

Провайдеры WMI

Провайдеры WMI обеспечивают связь между менеджером объектов CIM и управляемыми ресурсами: провайдеры предоставляют для CIMOM данные об управляемом объекте, обрабатывают запросы от управляющих программ и генерируют сообщения о наступлении определенных событий (см. рис. 10.1).

При этом провайдер WMI общается с управляемым объектом с помощью специфического API этого объекта, а с CIMOM — посредством стандартного интерфейса прикладного программирования WMI (WMI API). Таким образом, провайдеры скрывают детали внутренней реализации управляемых объектов, позволяя CIMOM обращаться к этим объектам единообразно, используя один и тот же WMI API.

Фактически провайдеры WMI являются серверами COM или DCOM, которые представлены динамическими библиотеками (DLL), находящимися чаще всего в каталоге %SystemRoot%\System32\Wbem. WMI включает в себя множество встроенных (стандартных) провайдеров для операционных систем Windows 2000, Windows XP и Windows Server 2003, которые предназначены для получения данных из известных системных источников таких, как подсистема Win32, журналы событий, системный реестр, системные счетчики производительности. В табл. 10.1 приведено описание некоторых стандартных провайдеров, которые присутствуют во всех ранее перечисленных операционных системах.

Таблица 10.1. Некоторые стандартные провайдеры WMI
ПровайдерDLL-файлОписание
Провайдер каталога Active Directory(Active Directory provider)Dsprov.dllПозволяет обращаться к объектам Active Directory как к объектам WMI
Провайдер журнала событий (Event Log provider)Ntevt.dllОбеспечивает управление журналом событий (выборка по определенному критерию записей для чтения, создание резервных копий и очистка журнала, изменение настроек и т. д.). Также этот провайдер позволяет обрабатывать события, генерируемые журналом (например, добавление в журнал записи определенного типа)
Провайдер системных счетчиков производительности (Perfomance Counter provider)Wbemperf.dllОбеспечивает доступ к счетчикам производительности, т. е. к данным, позволяющим численно оценивать производительность системы
Провайдер реестра (Registry provider)Stdprov.dllПозволяет читать данные из реестра, создавать и модифицировать там ключи и разделы. Кроме этого, провайдер обеспечивает генерацию события WMI при изменении определенного ключа или ветви реестра
Провайдер SNMP-устройств (SNMP provider)Snmpincl.dllЯвляется шлюзом для доступа к системам и устройствам, которые управляются с помощью протокола SNMP (Simple Network Management Protocol)
Провайдер драйверов устройств (WDM provider)Wmiprov.dllПозволяет получить доступ к информации низкого уровня о драйверах устройств Windows Driver Model (WDM); в качестве таких устройств могут выступать, например, порты ввода/вывода или сетевые платы
Провайдер подсистемы Win32 (Win32 provider)Cimwin32.dllОбеспечивает доступ к информации о компьютере, операционной системе, подсистеме безопасности, дисках, периферийных устройствах, файловых системах, файлах, папках, сетевых ресурсах, принтерах, процессах, сервисах и т. п.
Провайдер инсталлированных программных продуктов (Windows Installer provider)Msiprov.dllПозволяет получить информацию об инсталлированном программном обеспечении

Технология WMI позволяет также создавать и устанавливать провайдеры сторонних поставщиков, с помощью которых можно будет, скажем, через WMI получать информацию о каких-то специфических устройствах или службах. Отметим, что свои провайдеры WMI имеются в таких продуктах Microsoft, как Application Center, Operations Manager, Systems Management Server, Internet Information Server, Exchange Server, SQL Server.

Менеджер объектов CIM

Задачей менеджера объектов CIM (CIMOM) является обеспечение взаимодействия между потребителями сервисов WMI (управляющими приложениями) и провайдерами WMI (см. рис. 10.1). CIMOM обрабатывает все запросы, которые поступают от управляющих приложений к WMI, и обеспечивает доставку к этим приложениям информации, полученной в результате выполнения таких запросов. Детальное описание функций CIMOM приведено далее.

В Windows функциональность менеджера CIM обеспечивает файл winmgmt.exe, который находится в каталоге %SystemRoot%\System32\Wbem (этот файл запускается как сервис).

Репозиторий CIM. Пространства имен

Повторим еще раз, что основной идеей, на которой базируется WMI, является возможность представить информацию о состоянии любого управляемого объекта в виде стандартной схемы. В качестве такой схемы выступает информационная модель CIM, которая является репозиторием (хранилищем) объектов и классов, моделирующих различные компоненты компьютерной системы.

Таким образом, CIM можно считать хранилищем классов, где класс — это модель (шаблон) управляемого объекта (напомним, что в качестве управляемых объектов могут выступать самые различные логические и физические компоненты компьютерной системы: жесткие диски, журналы событий, сетевые карты, файлы и папки, процессы, сервисы, процессоры и т. д.). С этой точки зрения CIM похожа на другие каталоги, которые используются в Windows (например, каталог файловой системы содержит объекты-файлы и объекты-папки, а каталог Active Directory — объекты-домены, объекты-пользователи, объекты-принтеры и т. д.) Однако важной особенностью CIM является то, что хранящиеся в ней классы чаще всего соответствуют динамически изменяемым ресурсам, поэтому объекты-экземпляры таких классов не хранятся постоянно в CIM, а создаются провайдером по запросу потребителя WMI. Связано это с тем, что состояние большинства WMI-совместимых устройств меняется очень быстро и постоянное обновление информации в CIM может значительно снизить общую производительность системы.

Замечание

Количество классов, имеющихся в CIM, сильно зависит от версии операционной системы. Например, в Windows Server 2003 в CIM хранится около 5 000 классов.

Классы, составляющие CIM, имеют свойства и методы и находятся в иерархической зависимости друг от друга — классы-потомки могут наследовать или переопределять свойства родительских классов, а также добавлять собственные свойства. Свойства описывают конфигурацию и текущее состояние управляемого ресурса, а методы позволяют выполнить над этим ресурсом определенные действия.

Классы CIM группируются в пространстве имен (namespaces), которые упорядочены иерархически (корневое пространство имен обозначается через Root). Пространство имен — это группа логически связанных друг с другом классов, которые относятся к какой-либо определенной технологии или области управления. Например, одно из наиболее часто используемых на практике пространств имен CIMV2 содержит классы, которые описывают компьютер и операционную систему; описание некоторых классов из этого пространства имен приведено в табл. 10.2.

Таблица 10.2. Некоторые классы из пространства имен Root\CIMV2
КлассОписание
Win32_BaseBoardОписывает системную (материнскую) плату. С помощью экземпляра этого класса можно, например, узнать серийный номер материнской платы
Win32_BusОписывает физические шины (например, шины PCI или USB) с точки зрения операционной системы Win32
Win32_ProcessorПредставляет процессоры, т. е. устройства, способные обрабатывать наборы машинных команд в системе Win32. В мультипроцессорной системе для каждого из процессоров существует отдельный экземпляр этого класса
Win32_DiskPartitionПозволяет получать информацию об имеющихся в системе разделах жестких дисков. Для каждого из разделов создается свой экземпляр этого класса
Win32_FloppyDriveОписывает имеющиеся в системе дисководы гибких дисков. Для каждого из дисководов создается свой экземпляр этого класса
Win32_KeyboardОписывает подключенную к компьютеру клавиатуру (например, отражаются количество функциональных клавиш или используемая раскладка)
Win32_BIOSСвойства этого класса представляют атрибуты базовой системы ввода/вывода (BIOS): компания-производитель, версия, номер сборки и т. д.
Win32_OperatingSystemОписывает установленную на компьютере операционную систему. В свойствах экземпляра этого класса хранятся номер сборки системы, используемая по умолчанию кодовая страница, время последней перезагрузки, число пользовательских лицензий и т.д.
CIM_DataFileЭкземпляры этого класса соответствуют логическим файлам. Кроме свойств, описывающих различные атрибуты файла, в классе CIM_DataFile имеются методы, которые позволяют производить над файлом некоторые действия (копировать, перемещать, переименовывать или удалять его, изменять разрешения на файл и т. д.)
Win32_DirectoryЭкземпляры этого класса соответствуют каталогам файловой системы. Свойства и методы класса Win32_Directory практически совпадают со свойствами и методами класса CIM_DataFile
Win32_DesktopВ свойствах экземпляров класса Win32_Desktop хранятся характеристики рабочих столов пользователей: частота мигания курсора, имя исполняемого файла заставки, частота вызова заставки, имя файла с рисунком рабочего стола и т. д.
Win32_ShareЭкземпляры этого класса соответствуют общим ресурсам, имеющимся в системе (общие папки, принтеры, именованные каналы и т. д.)
Win32_ServiceЭкземпляры данного класса позволяют получать информацию о службах (services) операционной системы Win32 и управлять ими (запускать, останавливать и т. д.)
Win32_ProcessКаждому запущенному в системе процессу соответствует экземпляр класса Win32_Process. Свойства этого класса позволяют получить полную информацию о процессе (имя, идентификатор, время создания, приоритет и т. д.), а с помощью методов данного класса можно создавать новые процессы, менять приоритеты, завершать процессы и т. д.

Количество и содержимое пространств имен зависит от операционной системы, а также от используемой версии WMI и установленных в системе приложений. Отметим при этом, что в любом варианте установки WMI имеются четыре предопределенных пространства имен, которые всегда находятся на один уровень ниже корневого пространства имен: CIMV2, Default, Security и WMI. Некоторые пространства имен содержат другие пространства. Например, в CIMV2 определены подпространства имен Applications и ms_409.

В операционных системах Windows Server 2003 и Windows XP репозиторий CIM физически располагается в четырех файлах каталога %SystemRoot%\System32\Wbem\ Repository\FS:

Путь к классам и объектам CIM

Все классы внутри одного пространства имен должны иметь уникальные имена (при этом имена классов из разных пространств могут совпадать), причем класс в одном пространстве имен не может иметь предка или потомка из другого пространства. Для идентификации классов и объектов внутри пространства имен в CIM нужно задавать путь к этим классам и объектам (object path), аналогично тому, как это делается, например, в пространства имен файловой системы. Напомним, что любой файл на диске однозначно определяется полным путем к нему следующим образом: нужно указать имя устройства, после которого следуют одно или несколько имен каталогов и непосредственно имя файла. Другими словами, в файловой системе используется иерархическая структура каталогов и файлов различной степени вложенности. В отличие от этого, у пространств имен CIM имеется только один уровень в глубину, а для идентификации объекта задействуются свойства объектов, которые рассматриваются как ключи. Другими словами, каждый экземпляр класса должен быть однозначно идентифицируемым по своим ключевым параметрам. Полный путь к хранящемуся в CIM классу или объекту-экземпляру класса (управляемому устройству) имеет следующую структуру:

[\\ComputerName][\Namespace][:ClassName][.KeyProperty1=Value1
[,KeyProperty2=Value2…]]

Здесь \\ComputerName — это сетевое имя компьютера, на котором расположен нужный класс или объект (для задания имени локального компьютера можно использовать символ "."), \Namespace — название пространства имен, в котором находится этот класс или объект, :ClassName — имя класса. Параметры KeyProperty1 и Value1, KeyProperty2 и Value2, …, задают список ключевых пар (свойство-значение) объекта. Например, следующий путь

\\.\CIMV2:Win32_Process.Name="Notepad.exe"

определяет процесс (экземпляр класса Win32_Process из пространства имен CIMV2) с именем "Notepad.exe", который запущен на локальной машине.

Другой пример — построение пути к объекту WMI, соответствующему десятой записи в журнале событий приложений на компьютере с именем \\CPU3. В WMI для представления записей в журнале событий строятся объекты-экземпляры класса Win32_NTLogEvent. Этот класс хранится в пространстве имен CIMV2, а для идентификации конкретного экземпляра класса Win32_NTLogEvent используются два ключевых свойства символьного типа: LogFile (тип журнала событий) и RecordNumber (символьное представление порядкового номера записи в журнале). Поэтому полный путь к объекту в нашем примере будет иметь следующий вид:

\\CPU3\CIMV2:Win32_NTLogEvent.LogFile="Application",RecordNumber="10"

Безопасность при работе с WMI

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

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

Дополнительная политика безопасности в WMI реализована на уровне пространств имен и на уровне протокола DCOM (Distributed COM). Перед тем, как более подробно рассмотреть эти типы безопасности WMI, напомним основные общие понятия, связанные с безопасностью в Windows.

Безопасность в Windows NT/2000/XP основана на именах пользователей и их паролях. Когда в этих версиях Windows заводится пользователь, то его учетной записи присваивается уникальный идентификатор безопасности (Security IDentifier, SID). На основе SID для пользователя формируется маркер доступа (Access Token), в который также добавляется список групп, членом которых является пользователь, и список привилегий, которыми он обладает (например, остановка служб или выключение компьютера). Этот маркер доступа присваивается и всем процессам, которые запускает пользователь. Далее каждый объект операционной системы, доступ к которому определяет система безопасности (это может быть файл, процесс, служба и т. д.) имеет дескриптор безопасности (Security Descriptor, SD), в котором хранится таблица контроля доступа (Access Control List, ACL) для этого объекта. При обращении пользователя или процесса, запущенного пользователем, к объекту происходит сравнение маркера доступа этого пользователя с таблицей контроля доступа и в зависимости от результатов выдается или отклоняется разрешение на выполнение запрашиваемых действий над объектом.

Механизм безопасности WMI на уровне пространств имен соответствует общей модели безопасности Windows NT/2000/XP. Каждое пространство имен может иметь собственный дескриптор безопасности, в котором хранится таблица контроля доступа (ACL). Каждая запись таблицы контроля доступа (Access Control Entry, ACE) содержит информацию о том, какие права (разрешения) имеет определенный пользователь при выполнении различных операций в этом пространстве имен (список разрешений, используемых при работе с пространством имен, приведен в табл. 10.3).

Таблица 10.3. Разрешения безопасности для пространства имен WMI
Разрешение Описание
Выполнение методов (Execute Methods)Позволяет вызывать методы классов из определенного пространства имен. Будет ли при этом метод выполнен или произойдет отказ зависит от того, имеет ли пользователь разрешение на выполнение этой операции в операционной системе
Полная запись (Full Write)Позволяет создавать и модифицировать подпространства имен, системные классы и экземпляры классов
Частичная запись (Partial Write)Позволяет создавать и модифицировать любые статические классы и экземпляры несистемных классов
Запись поставщика (Provider Write)Позволяет записывать в репозиторий CIM классы провайдеров WMI и экземпляры этих классов
Включить учетную запись (Enable Account)Предоставляет право чтения пространства имен WMI. Пользователи, имеющие это разрешение, могут запускать на локальном компьютере сценарии, которые читают данные WMI
Включить удаленно (Remote Enable)Разрешает пользователям получить доступ к пространству имен WMI на удаленном компьютере. По умолчанию этим разрешением обладают только администраторы, обычные пользователи не могут получать данные WMI с удаленных машин
Прочесть безопасность (Read Security)Позволяет читать дескриптор безопасности для пространства имен WMI без возможности его модификации
Изменение правил безопасности (Edit Security)Позволяет изменять дескриптор безопасности для пространства имен WMI

Все записи таблицы контроля доступа сохраняются в репозитории WMI. Разрешения WMI, определенные для конкретного пространства имен, также применяются (наследуются) ко всем подпространствам имен и классам, которые определены в этом пространстве. Собственные разрешения безопасности для отдельного класса WMI определить нельзя.

В Windows NT/2000/XP по умолчанию группа администраторов обладает всеми разрешениями из табл. 10.3, а для остальных пользователей включена учетная запись (Enable Account), разрешено вызывать методы (Execute Methods) и записывать в CIM экземпляры классов провайдеров (Provider Write).

Администратор может изменить разрешения для определенных пользователей с помощью утилиты для настройки параметров WMI (оснастка wmimgmt.msc консоли управления MMC).

Для доступа к инфраструктуре WMI на удаленном компьютере используется коммуникационный протокол DCOM (Distributed COM). При этом пользователь, который запускает сценарий или подключается к WMI с помощью специальных утилит, выступает в качестве клиента, а объект WMI, к которому идет обращение, является сервером. Для того чтобы определить, какой маркер доступа будет применяться при работе с WMI на удаленном компьютере, используются стандартные уровни олицетворения протокола DCOM (DCOM Impersonation Levels), которые описаны в табл. 10.4.

Таблица 10.4. Уровни олицетворения DCOM
Уровень Описание
Анонимный доступ (Anonymous)Объект-сервер не имеет права получить информацию о пользователе или процессе, который обращается к данному объекту (иными словами, объект не может олицетворить клиента). Этот уровень олицетворения в WMI не используется
Идентификация (Identify)Объект-сервер может запросить маркер доступа, связанный с клиентом, но не может произвести олицетворение. В сценариях WMI этот уровень олицетворения используется редко, т. к. в этом случае нельзя запускать сценарии WMI на удаленных машинах
Олицетворение (Impersonate)Объект-сервер может пользоваться всеми правами и привилегиями, которыми обладает клиент. В сценариях WMI рекомендуется использовать именно этот уровень олицетворения, при этом сценарий WMI на удаленной машине сможет выполнять все действия, которые разрешено осуществлять пользователю, запустившему этот сценарий
Делегирование (Delegate)Объект-сервер, к которому обращается клиент, может обратиться от имени клиента к другому объекту-серверу. Делегирование позволяет сценарию использовать на удаленной машине маркер доступа запустившего его пользователя, а также использовать этот маркер для доступа к объектам WMI на других рабочих станциях. Применение данного уровня олицетворения связано с потенциальным риском, поэтому делегирование в сценариях WMI следует применять только в случае особой необходимости

Выбираемый по умолчанию уровень олицетворения зависит от версии WMI на целевом компьютере. В версиях WMI ниже 1.5 по умолчанию используется уровень Идентификация ( Identify ), в версии WMI 1.5 и выше — уровень Олицетворение (Impersonate). При необходимости можно изменить уровень олицетворения по умолчанию — для этого необходимо записать наименование нужного уровня (например, Impersonate или Delegate ) в следующий ключ реестра:

HKEY_LOCAL_MACHINE\Software\Microsoft\Wbem\
  Scripting\Default Impersonation Level

Протокол DCOM также предоставляет возможность запросить для соединения WMI определенный уровень аутентификации (проверки подлинности) и конфиденциальности (табл. 10.5).

Таблица 10.5. Уровни проверки подлинности DCOM
Уровень Описание
Отсутствует (None)Проверка подлинности отсутствует
По умолчанию (Default)Для выбора уровня проверки подлинности используются стандартные настройки безопасности. Рекомендуется использовать именно этот уровень, т. к. здесь к клиенту будет применен уровень проверки подлинности, который задается сервером
Подключений (Connect)Клиент проходит проверку подлинности только во время подключения к серверу. После того как соединение установлено, никаких дополнительных проверок не производится
Вызовов (Call)Клиент проходит проверку подлинности в начале каждого вызова во время приема запросов сервером. При этом заголовки пакетов подписываются, однако сами данные (содержимое пакетов), передаваемые между клиентом и сервером, не подписываются и не шифруются
Пакетов (Pkt)Проверке подлинности подвергаются все пакеты данных, которые поступают серверу от клиентов. Так же, как и при проверке подлинности на уровне вызовов, заголовки пакетов подписываются, но не шифруются. Сами пакеты не подписываются и не шифруются
Целостности пакетов (PktIntegrity)Все пакеты данных проходят проверку подлинности и целостности, т. е. проверяется, что содержимое пакета не было изменено во время передачи от клиента серверу. При этом данные подписываются, но не шифруются
Секретности пакетов (PktPrivacy)Все пакеты данных проходят проверку подлинности и целостности, при этом данные подписываются и шифруются, что обеспечивает конфиденциальность передаваемых данных

Отметим, что DCOM может и не установить запрашиваемый уровень проверки подлинности. Например, при локальной работе с WMI всегда используется уровень секретности пакетов (PktPrivacy). Нужные уровни олицетворения и проверки подлинности можно указать в явном виде в момент соединения с WMI (этот процесс описан в лекции 12).

Лекция 11. Структура классов WMI

Описываются основные типы классов информационной схемы CIM. Обсуждаются атрибуты классов WMI: свойства, методы, а также квалификаторы классов, свойств и методов. Рассматриваются инструменты для интерактивной работы с объектной моделью WMI

Структура классов WMI

Напомним, что всякому ресурсу, управляемому с помощью WMI, соответствует специальный класс WMI; каждый класс имеет четко определенную структуру и содержит свойства, методы и квалификаторы (свои квалификаторы могут быть также у свойств и методов). Классы описываются с помощью специального языка MOF (Managed Object Format), который, в свою очередь, базируется на языке IDL (Interface Definition Language), применяемом для описания интерфейсов COM-объектов. После определения структуры класса с помощью MOF разработчик может добавить откомпилированное представление этого класса в репозиторий CIM с помощью стандартной утилиты mofcomp.exe.

Подробнее понятия свойств, методов и квалификаторов будут обсуждаться далее, а начнем мы с типизации классов CIM.

Основные типы классов CIM

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

Кроме трех основных типов классов в CIM выделяется еще один специальный тип — ассоциативный класс (association class) — это абстрактный, статический или динамический класс, который описывает логическую связь между двумя классами или управляемыми ресурсами (например, ассоциативный класс Win32_SystemProcesses связывает класс Win32_Process, экземпляры которого соответствуют запущенным в системе процессам, с классом Win32_ComputerSystem, в котором представлены общие настройки компьютерной системы).

Кроме этого, все классы CIM можно разделить на четыре группы по принадлежности к различным информационным моделям.

Свойства классов WMI

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

Напомним, что для просмотра списка всех служб, установленных на компьютере, можно воспользоваться оснасткой Службы (Services) консоли управления MMC (рис. 11.1).

Службы, зарегистрированные на локальном компьютере


увеличить изображение

Рис. 11.1.  Службы, зарегистрированные на локальном компьютере

Параметры определенной службы можно просматривать и изменять с помощью диалогового окна с несколькими вкладками, которое появляется после выбора этой службы в правом окне консоли (рис. 11.2).

Параметры службы Журнал событий (Event Log)


Рис. 11.2.  Параметры службы Журнал событий (Event Log)

Службам Windows в WMI соответствуют экземпляры класса Win32_Service; основные свойства этого класса приведены в табл. 11.1.

Таблица 11.1. Некоторые свойства класса Win32_Service
Свойство Описание
AcceptPauseСвойство логического типа, значение которого равно True, если службу можно приостановить, и равно False в противном случае
AcceptStopСвойство логического типа, значение которого равно True, если службу можно остановить, и равно False в противном случае
CaptionКраткое описание службы
DescriptionПолное описание службы
DesktopInteractСвойство логического типа, значение которого равно True, если служба может взаимодействовать с рабочим столом пользователей, и равно False в противном случае
DisplayNameИмя службы, которое выводится в списке служб
ErrorControlСтрока, задающая действие программы загрузки, которое будет выполнено в случае возникновения сбоя при запуске службы во время загрузки операционной системы: Ignore — пользователю не будет выведено никаких сообщений о сбое, Normal — будет выведено сообщение о сбое при запуске службы, Critical — система попытается автоматически произвести перезагрузку в хорошей конфигурации, Unknown — действие для подобного типа ошибок не определено
NameИмя службы
PathNameПолный путь к бинарному файлу, соответствующему службе
ProcessIdУникальный идентификатор службы
ServiceTypeСтрока, описывающая тип службы: Kernel Driver, File System Driver, Adapter, Recognizer Driver, Own Process, Share Process, Interactive Process
StartedСвойство логического типа, значение которого равно True, если служба была запущена, и равно False в противном случае
StartModeСтрока, описывающая способ загрузки службы: Boot (применяется только при загрузке служб для драйверов), System (применяется только при загрузке служб для драйверов), Auto (служба загружается автоматически), Manual (служба может быть запущена вручную), Disabled (службу запустить нельзя)
StartNameУчетная запись, от имени которой запускается служба
StateТекущее состояние службы: Stopped (остановлена), Start Pending (стартует), Stop Pending (останавливается), Running (запущена), Continue Pending (возвращается в активное состояние), Pause Pending (приостанавливается), Paused (приостановлена), Unknown (состояние службы определить не удалось)
WaitHintПримерное время (в миллисекундах), необходимое для выполнения операций приостановки, остановки или запуска службы

Как мы видим, многие свойства класса Win32_Service соответствуют элементам ввода в диалоговом окне свойств службы. Например, для экземпляра класса Win32_Service, который представляет службу Журнал событий (Event Viewer) свойства Name, DisplayName, Description и StartMode равны соответственно Eventlog, Журнал событий, Обеспечивает поддержку сообщений журналов событий, выдаваемых Windows-программами и компонентами системы, и просмотр этих сообщений. Эта служба не может быть остановлена и Авто (см. рис. 11.2).

Рассмотрим теперь класс Win32_Process, экземпляры которого соответствуют запущенным в операционной системе процессам. Напомним, что информацию о всех процессах можно получить с помощью Диспетчера задач (Task Manager), запускаемого нажатием клавиш <Ctrl>+<Alt>+<Del> (рис. 11.3).

Процессы, запущенные на локальном компьютере


Рис. 11.3.  Процессы, запущенные на локальном компьютере

Количество выводимых на экран параметров для процессов зависит от настроек Диспетчера задач (Task Manager): выбрав в меню Вид (View) пункт Выбрать столбцы (Choose columns), можно отметить интересующие нас параметры (рис. 11.4).

Настройка выводимых параметров для процессов


Рис. 11.4.  Настройка выводимых параметров для процессов

Параметрам запущенного процесса соответствуют свойства класса Win32_Process ; некоторые из этих свойств приведены в табл. 11.2.

Таблица 11.2. Некоторые свойства класса Win32_Process
СвойствоОписание
CaptionКороткое текстовое описание процесса
CommandLineКомандная строка, используемая для запуска процесса
CreationDateВремя начала выполнения процесса
DescriptionПолное описание процесса
ExecutablePathПолный путь к исполняемому файлу процесса
HandleCountОбщее количество дескрипторов, открытых в настоящее время процессом (равно общему количеству дескрипторов, открытых каждым потоком в процессе)
MaximumWorkingSetSizeМаксимально возможный размер рабочего набора процесса (рабочий набор процесса — это набор страниц, доступных процессу в физической оперативной памяти)
MinimumWorkingSetSizeМинимально возможный размер рабочего набора процесса
NameИмя процесса
OtherOperationCountЧисло выполненных операций ввода/вывода, отличных от операции чтения или записи
OtherTransferCountРазмер данных, переданных в процессе выполнения операций, отличных от операции чтения или записи
PageFileUsageРазмер части файла подкачки, которая используется процессом в настоящее время
ParentProcessIDУникальный идентификатор родительского процесса, создавшего данный процесс
PeakPageFileUsageМаксимальный размер части файла подкачки, которая использовалась процессом за все время его работы
PeakVirtualSizeМаксимальное значение размера виртуального адресного пространства, которое использовалось процессом единовременно
PeakWorkingSetSizeМаксимальное значение размера рабочего набора процесса за все время работы
PriorityПриоритет процесса (минимальному приоритету соответствует значение 0, максимальному — 31)
ProcessIDУникальный идентификатор процесса. Значение этого свойства актуально с момента создания процесса до окончания его работы
ReadOperationCountЧисло выполненных процессом операций чтения
ReadTransferCountРазмер прочитанных данных
ThreadCountЧисло активных потоков в процессе
VirtualSizeТекущий размер виртуального адресного пространства в байтах, используемого процессом
WorkingSetSizeРазмер памяти в байтах, необходимый для успешного выполнения процесса в операционной системе, использующей страничную организацию памяти
WriteOperationCountЧисло выполненных процессом операций записи
WriteTransferCountРазмер записанных данных

Отметим, что в основном в WMI свойства классов доступны только для чтения, однако значения определенных свойств в экземплярах некоторых классов можно изменять напрямую (для этого применяется специальный метод Put_() ). Например, в экземплярах класса Win32_LogicalDisk, которые соответствуют логическим дискам, можно изменять свойство VolumeName, где хранится метка соответствующего диска.

Замечание

Количество свойств, значения которых можно изменять, зависит от операционной системы. Например, в Windows 2000 для записи доступны только 39 свойств, а в Windows XP — 145 свойств.

Для того чтобы узнать, является ли определенное свойство доступным для записи, нужно проверить значение квалификатора Write этого свойства.

Методы классов WMI

Методы класса позволяют выполнять те или иные действия над управляемым ресурсом, которому соответствует этот класс (так как не над каждым ресурсом можно производить какие-либо операции, то не у всякого класса есть методы). В табл. 11.3 и 11.4 описаны, например, методы, которые имеются у классов Win32_Service (службы Windows) и Win32_Process (процессы Windows).

Таблица 11.3. Методы класса Win32_Service
Метод Описание
StartService()Запускает службу
StopService()Остановливает службу
PauseService()Приостановливает службу
ResumeService()Возобновляет работу службы
UserControlService(n)Посылает службе заданный пользователем код n (число от 128 до 255)
Create(Name, DisplayName, PathName, ServiceType, ErrorControl, StartMode, DesktopInteract, StartName, StartPassword, LoadOrderGroup, LoadOrderGroupDependencies, ServiceDependencies)Создает службу
Change(DisplayName, PathName, ServiceType, ErrorControl, StartMode, DesktopInteract, StartName, StartPassword, LoadOrderGroup, LoadOrderGroupDependencies, ServiceDependencies)Изменяет параметры службы
ChangeStartMode(StartMode)Изменяет тип загрузки службы. Символьный параметр StartMode может принимать следующие значения: Boot (применяется только при загрузке служб для драйверов), System (применяется только при загрузке служб для драйверов), Auto (служба загружается автоматически), Manual (служба может быть запущена вручную), Disabled (службу запустить нельзя)
Delete()Удаляет существующую службу

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

Перейдем к рассмотрению методов класса Win32_Process, которые описаны в табл. 11.4.

Таблица 11.4. Методы класса Win32_Process
Метод Описание
AttachDebugger()Запускает отладчик, установленный в системе по умолчанию, для отладки процесса
Create(CommandLine, CurrentDirectory, ProcessStartupInformation, ProcessId)Создает новый не интерактивный процесс
GetOwner(User,Domain)После выполнения этого метода в переменной User будет записано имя пользователя, создавшего процесс (владельца процесса), а в переменной Domain — имя домена, в котором запущен этот процесс
GetOwnerSid(Sid)Позволяет получить в переменной Sid идентификатор безопасности (Security IDentifier, SID) владельца процесса
SetPriority(Priority)Устанавливает приоритет процесса. Числовой параметр Priority определяет требуемый приоритет и может принимать следующие значения: 64 (низкий), 16 384 (ниже среднего), 32 (средний), 32 768 (выше среднего), 128 (высокий), 256 (процесс выполняется в реальном времени)
Terminate(Reason)Завершает процесс и все его потоки. Числовой параметр Reason задает код выхода, который будет сообщен операционной системе после завершения процесса

Таким образом, методы класса Win32_Process позволяют выполнять над процессами те же действия, которые можно осуществить в Диспетчере задач Windows с помощью контекстного меню, появляющегося после щелчка правой кнопкой мыши над выделенным процессом в списке (см. рис. 11.5), и кнопки Завершить процесс (Terminate process).

Контекстное меню, позволяющее выполнять действия над определенным процессом


Рис. 11.5.  Контекстное меню, позволяющее выполнять действия над определенным процессом

Квалификаторы классов, свойств и методов

В WMI для классов, свойств и методов можно задать так называемые квалификаторы (qualifiers). Квалификаторы содержат дополнительную информацию о том классе, свойстве или методе, в котором они определены.

Квалификаторы классов

Квалификаторы классов предоставляют информацию о классе в целом. Например, тип класса описывает квалификаторы логического типа CIM_BOOLEAN с именами abstract (абстрактный класс), dynamic (динамический класс) и association (ассоциативный класс).

Один и тот же класс в различных операционных системах может иметь разное количество квалификаторов (версия WMI, поставляемая с Windows XP, соответствует спецификации CIM 2.5, а версии WMI в Windows 2000 и ниже – спецификации CIM 2.0). Для примера в таблице 11.5. приведено описание квалификаторов для класса Win32_Service в Windows XP.

Таблица 11.5. Квалификаторы класса Win32_Service
Квалификатор Тип Значение Описание
DynamicCIM_BOOLEANTrueТип класса
LocaleCIM_SINT321033Язык по умолчанию для класса или экземпляра класса
ProviderCIM_STRINGCIMWin32Имя провайдера класса
SupportsUpdateCIM_BOOLEANTrueУказывает на то, что класс поддерживает операцию изменения (обновления) экземпляров
UUIDCIM_STRING{8502C4D9-5FBB-11D2-AAC1-006008C78BC7}Универсальный уникальный идентификатор класса

Класс Win32_Process позволяет создавать новые процессы и завершать уже существующие, поэтому в данном классе появляется несколько новых квалификаторов (табл. 11.6).

Таблица 11.6. Квалификаторы класса Win32_Process
Квалификатор Тип Значение Описание
CreateByCIM_STRINGCreateНазвание метода, при помощи которого создается экземпляр класса
DeleteByCIM_STRINGDeleteInstanceНазвание метода, при помощи которого уничтожается экземпляр класса
DynamicCIM_BOOLEANTrueТип класса
LocaleCIM_SINT321033Язык по умолчанию для класса или экземпляра класса
ProviderCIM_STRINGCIMWin32Имя провайдера класса
SupportsCreateCIM_BOOLEANTrueУказывает на то, что класс поддерживает операцию создания экземпляров
SupportsDeleteCIM_BOOLEANTrueУказывает на то, что класс поддерживает операцию уничтожения экземпляров
UUIDCIM_STRING{8502C4DC-5FBB-11D2-AAC1-006008C78BC7}Универсальный уникальный идентификатор класса
Квалификаторы свойств

Квалификаторы свойств позволяют определить тип данного свойства (квалификатор CIMType ), доступность его для чтения (квалификатор Read ) и записи (квалификатор Write ) и т. п. Для примера в табл. 11.7 приведено описание квалификаторов свойства ServiceType класса Win32_Service (напомним, что это свойство описывает тип службы).

Таблица 11.7. Квалификаторы свойства ServiceType класса Win32_Service
Квалификатор Тип Значение Описание
CIMTypeCIM_STRINGStringТип свойства
MappingStringsCIM_STRING | CIM_FLAG_ARRAYWin32API| Service Structures| QUERY_SERVICE_CONFIG| dwServiceTypeМножество значений (ключевых слов), по которым можно найти дополнительную информацию о данном свойстве
ReadCIM_BOOLEANTrueУказывает на то, что свойство доступно для чтения
ValueMapCIM_STRING | CIM_FLAG_ARRAYKernel Driver, File System Driver, Adapter, Recognizer Driver, Own Process, Share Process, Interactive ProcessНабор допустимых значений для свойства

Замечание

Напрямую с помощью метода Put_() можно изменять значения только тех свойств, у которых имеется квалификатор write со значением true.

Квалификаторы методов

Квалификаторы методов могут описывать множество допустимых значений, которые будут возвращаться методом (квалификатор ValueMap ), указывать права, которыми необходимо обладать для вызова метода (квалификатор Privileges ) и т. п. Для примера в табл. 11.8 приведено описание квалификаторов метода Create класса Win32_Process (напомним, что этот метод используется для запуска в системе нового процесса).

Таблица 11.8. Квалификаторы метода Create класса Win32_Process
Квалификатор Тип Значение Описание
ConstructorCIM_BOOLEANTrueУказывает на то, что данный метод используется для создания экземпляров класса
ImplementedCIM_BOOLEANTrueУказывает на то, что данный метод реализован в провайдере
MappingStringsCIM_STRING | CIM_FLAG_ARRAYWin32API| Process and Thread Functions| CreateProcessМножество значений (ключевых слов), по которым можно найти дополнительную информацию о данном методе
PrivilegesCIM_STRING | CIM_FLAG_ARRAYSeAssignPrimaryTokenPrivilege, SeIncreaseQuotaPrivilegeПеречисляет права, необходимые для выполнения данного метода
StaticCIM_BOOLEANTrueУказывает на то, что данный метод не может быть вызван из экземпляра класса
ValueMapCIM_STRING | CIM_FLAG_ARRAY0, 2, 3, 8, 9, 21, ..Набор возвращаемых данным методом значений

Замечание

Выполнять можно только те методы, у которых имеется квалификатор Implemented со значением True.

Интерактивная работа с объектами WMI

При изучении WMI очень полезно с помощью графических утилит просматривать иерархическую структуру классов и связи между различными объектами CIM. Для просмотра объектной модели WMI можно воспользоваться специальный тестер WMI (стандартная программа в операционных системах Windows 2000/XP) или утилитами из разработанного Microsoft дополнительного пакета WMI Tools.

Тестер WMI (WBEMTest)

Тестер WMI (wbemtest.exe) — это графическая утилита, с помощью которой можно взаимодействовать с инфраструктурой WMI на локальном или удаленном компьютере. С помощью тестера WMI можно решать следующие задачи:

Исполняемый файл wbemtest.exe является стандартным компонентом WMI в любой операционной системе; устанавливается он в каталог %SystemRoot%\System32\Wbem. После запуска этого файла появляется диалоговое окно Тестер инструментария управления Windows (Windows Management Instrumentation Tester), с помощью которого можно получить доступ ко всем функциям тестера WMI (рис. 11.6).

Тестер WMI


Рис. 11.6.  Тестер WMI

Сразу после запуска большинство кнопок этого диалогового окна недоступны — ими можно будет воспользоваться только после подключения к подсистеме WMI. До подключения можно установить флажок Включить все привилегии (Enable all privileges), что позволит средствами WMI выполнять операции, для которых необходимы специальные привилегии в операционных системах Windows NT/2000/XP (например, перезагрузку компьютера).

Отметим, что работа с тестером WMI предполагает хорошее знание структуры CIM и умение составлять запросы на языке WQL. Для первоначального ознакомления и изучения структуры объектной модели WMI лучше воспользоваться пакетом WMI Tools.

Административные утилиты WMI (WMI Tools)

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

Если эти утилиты нужно установить в Windows 2000/XP/Server 2003, то инсталляционный файл WMITools.exe можно свободно скачать с сервера Microsoft (http://download.microsoft.com/download/.NetStandardServer/Install/V1.1/NT5XP/EN-US/WMITools.exe).

В случае же Windows 9x/NT 4.0 необходимо установить комплект инструментальных средств разработки SDK WMI, в состав которого также входят все описанные утилиты. Инсталляционный файл wmisdk.exe можно свободно скачать с сервера Microsoft (http://download.microsoft.com/download/platformsdk/x86wmi/1.1/W9XNT4/ EN-US/wmisdk.exe).

Административные утилиты WMI реализованы в виде элементов ActiveX, которые встроены в страницы HTML, поэтому для их корректной работы необходимо, чтобы в системе был установлен браузер Microsoft Internet Explorer 5.0/6.0. Кроме этого, пользователь, который производит установку утилит WMI на компьютер, должен обладать правами администратора.

Подключение к пространству имен WMI

Для запуска любой из трех основных административных утилит WMI (WMI CIM Studio, WMI Object Browser или WMI Event Registration Tool) нужно выбрать соответствующий одноименный пункт в меню Пуск | Программы | WMI Tools (Start | Programs | WMI Tools). Первым шагом после запуска во всех этих утилитах является подключение к какому-либо пространству имен на локальном или удаленном компьютере с помощью диалогового окна Connect to namespace (рис. 11.7).

Ввод пространства имен WMI для подключения


Рис. 11.7.  Ввод пространства имен WMI для подключения

По умолчанию в этом окне предлагается подключиться к пространству имен CIMV2 на локальном компьютере (root\CIMV2). Путь к нужному пространству имен на локальном или удаленном компьютере можно либо написать вручную, либо выбрать это пространство с помощью кнопки Browse For Namespace.

Если компьютер, к которому предполагается подключиться, доступен в сети, то его можно найти и выбрать с помощью кнопки Network Neighborhood.

После ввода в поле Machine Name имени нужного компьютера, следует выбрать интересующее нас пространство имен из списка. Для этого нужно в поле Starting Namespace написать название корневого пространства имен (обычно это Root) и нажать на кнопку Connect. В результате на экран выводится диалоговое окно Login (в заголовке этого окна отображается также название запущенного приложения), в котором можно указать имя пользователя и пароль для учетной записи, от имени которой происходит подключение к пространству имен (рис. 11.8).

Диалоговое окно WMI CIM Studio Login


Рис. 11.8.  Диалоговое окно WMI CIM Studio Login

Напомним, что к пространству имен на локальном компьютере может получить доступ только текущий пользователь, поэтому в случае локальной машины флажок Login as current user установлен, а поля Username, Password и Authority недоступны для редактирования. К пространству имен на удаленной машине можно подключаться как от имени текущего пользователя (для этого следует установить флажок Login as current user), так и от имени другого пользователя (в этом случае нужно снять флажок Login as current user и внести в поля Username и Password имя пользователя в виде domain\user и пароль соответственно).

Также в окне Login с помощью кнопки Options>> можно настроить дополнительные параметры подключения к инфраструктуре WMI (задать уровни олицетворения и проверки подлинности протокола DCOM, а также указать требуемые привилегии операционной системы).

После нажатия кнопки OK в окне Login и подключения к структуре WMI на нужном компьютере, в окне Browse For Namespace появится иерархический список всех классов из репозитория CIM на этом компьютере (рис. 11.9).

Выбор нужного пространства имен из списка


Рис. 11.9.  Выбор нужного пространства имен из списка

Выбрав требуемое пространство имен из списка и нажав кнопку OK, мы вновь попадаем в диалоговое окно Login (см. рис. 11.8), где нужно ввести необходимую информацию и нажать кнопку OK.

Замечание

Независимо от способа подключения пользователь должен иметь доступ к выбранному пространству имен WMI.

Для изучения структуры классов WMI можно воспользоваться утилитой WMI CIM Studio или WMI Object Browser.

WMI CIM Studio

Утилита WMI CIM Studio является универсальным инструментом при работе со схемой CIM, которая позволяет:

Приложение WMI CIM Studio реализовано в виде двух окон, которые открываются в браузере Internet Explorer (рис. 11.10).

Главное окно утилиты WMI CIM Studio


увеличить изображение

Рис. 11.10.  Главное окно утилиты WMI CIM Studio

Левое окно называется проводником классов (Class Explorer), а правое — просмотрщиком классов (Class Viewer). Выбрав класс в левом окне, можно просмотреть информацию о нем в правом окне.

WMI Object Browser

Утилита WMI Object Browser позволяет осуществлять навигацию по иерархическому дереву объектов WMI, просматривать и редактировать (если это возможно) свойства, методы, квалификаторы и ассоциации экземпляров классов, а также выполнять методы этих экземпляров. Главное отличие WMI Object Browser от WMI CIM Studio состоит в том, что в WMI CIM Studio мы пользуемся списком классов CIM в выбранном пространстве имен WMI, а в WMI Object Browser на экран выводится дерево объектов, причем в качестве корневого объекта здесь может использоваться произвольный экземпляр выбранного нами класса, а само дерево объектов строится с помощью ассоциативных классов (рис. 11.11).

Утилита WMI Object Browser


увеличить изображение

Рис. 11.11.  Утилита WMI Object Browser

Можно сказать, что утилита WMI Object Browser разработана, в большей мере, для применения системными администраторами, которые могут не иметь детального представления о назначении конкретных классов WMI и о структуре CIM вообще. Здесь вся информация (схема), которая содержится в репозитории CIM, представлена в более понятном и наглядном виде, чем в WMI CIM Studio. Например, по умолчанию корневым объектом в пространстве имен CIMV2 на локальном или удаленном компьютере является экземпляр класса Win32_ComputerSystem, у которого значение свойства Name совпадает с именем этого компьютера. Поэтому в корне дерева стоит объект с именем компьютера, а ниже в иерархическом порядке располагаются все его зависимые объекты (логические и физические компоненты этого компьютере).

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

Напомним, что для запуска WMI Object Browser, как и других административных утилит WMI, нужно выбрать одноименный пункт в меню Пуск | Программы | WMI Tools (Start | Programs | WMI Tools), после чего производится подключение к нужному пространству имен на локальном или удаленном компьютере.

Внешне утилита WMI Object Browser очень похожа на WMI CIM Studio, здесь также имеются два окна, которые открываются в браузере Internet Explorer (см. рис. 11.11). Левое окно называется проводником объектов (Object Explorer), а правое — просмотрщиком объектов (Object Viewer). Выбрав объект в левом окне, можно просмотреть информацию о нем в правом окне.

Лекция 12. Сценарии WSH для работы с объектной моделью WMI

Рассматриваются механизм работы и основные типы сценариев WSH, использующихся для доступа к WMI. Даются примеры сценариев для подключения к подсистеме WMI на локальном или удаленном компьютере, получения экземпляров объектов WMI и вызова их методов

Сценарии WSH для работы с объектной моделью WMI

Здесь мы подробно остановимся на механизме работы подобных сценариев, в основе которого лежит библиотека поддержки сценариев WMI (WMI Scripting Library), а также рассмотрим на примерах все основные типы сценариев WMI.

Сразу отметим, что все сценарии данной лекции написаны на языке VBScript, который позволяет напрямую работать с выходными параметрами методов объектов WMI, а также обрабатывать элементы коллекций без создания дополнительного объекта Enumerator.

Объектная модель библиотеки поддержки сценариев WMI

Итак, для того чтобы получить доступ к WMI с помощью сценариев, необходима специальная библиотека поддержки сценариев WMI (WMI Scripting Library), которая располагается в файле wbemdisp.dll в каталоге %SystemRoot%\System32\Wbem (в Windows Server 2003, Windows XP, Windows 2000 и Windows NT) или в каталоге %WinDir%\System\Wbem (в Windows Me и Windows 9x). В этой библиотеке определяются несколько связанных друг с другом объектов–серверов автоматизации (например, в Windows XP и Windows Server 2003 число этих объектов равно двадцати четырем), позволяющих из сценария осуществить авторизованное подключение к службе WMI на локальном или удаленном компьютере и получить доступ к классам и объектам из определенного пространства имен.

При этом связь между репозиторием CIM и объектами библиотеки поддержки сценариев WMI реализована следующим образом: после подключения к службе WMI и получения с помощью этих объектов доступа к экземпляру управляемого ресурса WMI, из сценария становится возможным напрямую использовать все свойства и методы, описанные в соответствующем этому ресурсу классе CIM, как если бы эти свойства и методы были частью библиотеки поддержки сценариев WMI. Это достигается с помощью полиморфного объекта SWbemObject, который может представлять либо экземпляр управляемого ресурса WMI, либо определение класса WMI. Полиморфным этот объект называется из-за того, что набор его свойств зависит от управляемого ресурса (класса CIM), которому он сопоставлен. Например, для класса Win32_Process объект SWbemObject будет среди прочих иметь свойства Handle и ExecutionState, а для класса Win32_Service — свойства ServiceType и StartMode.

В таблице 12.1 кратко описаны основные объекты библиотеки поддержки сценариев WMI, которые мы будем наиболее часто использовать в наших примерах.

Таблица 12.1. Основные объекты библиотеки поддержки сценариев WMI
Объект Описание
SWbemLocatorИспользуется для установления связи с пространством имен WMI на локальном или удаленном компьютере. В языке VBScript создается с помощью функции CreateObject, в JScript — с помощью конструкции new ActiveXObject, в WSH — с помощью метода CreateObject объекта WScript
SWbemServicesПозволяет выполнять действия над классами и объектами в пространстве имен WMI (создание, получение доступа, изменение и удаление классов или экземпляров классов). В языках VBScript и JScript создается с помощью функции GetObject, в WSH — с помощью метода GetObject объекта WScript
SWbemObjectSetКоллекция объектов SWbemObject, которая может быть получена путем вызова методов других объектов библиотеки поддержки сценариев WMI (например, методов ExecQuery или InstancesOf объекта SWbemservices )
SWbemObjectПредставляет либо экземпляр управляемого ресурса WMI, либо определение класса WMI. В языках VBScript и JScript создается с помощью функции GetObject, в WSH — с помощью метода GetObject объекта Wscript
SWbemMethodSetКоллекция объектов SWbemMethod. Хранится в свойстве Methods_ соответствующего объекта SWbemObject, не может быть создана в сценарии напрямую с помощью CreateObject или GetObject
SWbemMethodПозволяет получить описание метода объекта WMI. Этот объект не может быть создан в сценарии напрямую с помощью CreateObject или GetObject
SWbemPropertySetКоллекция объектов SWbemProperty. Хранится в свойстве Properties_ соответствующего объекта SWbemObject, не может быть создана в сценарии напрямую с помощью CreateObject или GetObject
SWbemPropertyПредставляет одно свойство управляемого объекта WMI. Этот объект не может быть создан в сценарии напрямую с помощью CreateObject или GetObject
SWbemQualifierSetКоллекция объектов SWbemQualifier. Хранится в свойстве Qualifiers_ соответствующего объекта SWbemObject, SWbemProperty или SWbemMethod. Эта коллекция не может быть создана в сценарии напрямую с помощью CreateObject или GetObject
SWbemQualifierПредставляет либо квалификатор класса или экземпляра класса WMI, либо квалификатор свойства или метода объекта WMI. Этот объект не может быть создан в сценарии напрямую с помощью CreateObject или GetObject
SWbemObjectPathПозволяет построить и проверить путь к объекту WMI. В языке VBScript создается с помощью функции CreateObject, в JScript — с помощью конструкции new ActiveXObject, в WSH — с помощью метода CreateObject объекта WScript
SWbemNamedValueSetКоллекция объектов SWbemNamedValue. В языке VBScript создается с помощью функции CreateObject, в JScript — с помощью конструкции new ActiveXObject, в WSH — с помощью метода CreateObject объекта Wscript
SWbemNamedValueИспользуется для передачи дополнительной информации при некоторых вызовах WMI. Этот объект не может быть создан в сценарии напрямую с помощью CreateObject или GetObject
SWbemLastErrorСодержит расширенную информацию о произошедшей ошибке WMI. В языке VBScript создается с помощью функции CreateObject, в JScript — с помощью конструкции new ActiveXObject, в WSH — с помощью метода CreateObject объекта Wscript
SWbemSecurityПозволяет читать или записывать информацию об установках безопасности для определенного объекта WMI. Хранится в свойстве Security_ объектов SWbemLocator, SWbemServices, SWbemObjectSet, SWbemObject, SWbemObjectPath, SWbemLastError, SWbemEventSource
SWbemPrivilegeSetКоллекция объектов SWbemPrivilege. Хранится в свойстве Privileges объекта WbemSecurity
SWbemPrivilegeПозволяет установить или удалить привилегию, необходимую для доступа к объекту WMI. Этот объект не может быть создан в сценарии напрямую с помощью CreateObject или GetObject
SWbemEventSourceСоответствует событию WMI, которое задается с помощью метода ExecNotificationQuery объекта SWbemServices. Этот объект не может быть создан в сценарии напрямую с помощью CreateObject или GetObject
SWbemSinkИспользуется для получения результатов выполнения асинхронных методов. В языке VBScript создается с помощью функции CreateObject, в JScript — с помощью конструкции new ActiveXObject, в WSH — с помощью метода CreateObject объекта Wscript

Соединение с подсистемой WMI

Первым шагом при работе с WMI из сценария является получение доступа к подсистеме WMI на локальном или удаленном компьютере. Для этого существуют два различных варианта: с использованием объекта SWbemLocator и с помощью так называемого WMI-моникера (WMI moniker) "WinMgmts:".

Соединение с помощью объекта SWbemLocator

Объект SWbemLocator позволяет установить соединение с определенным пространством имен WMI на удаленном компьютере от имени заданной учетной записи (на локальном компьютере соединение с WMI всегда производится от имени текущей учетной записи). Использование этого объекта бывает необходимо, если в сценарии нужно явно задать имя пользователя и пароль для подключения к пространству имен WMI, либо сценарий используется внутри HTML-страницы.

Для создания объекта SWbemLocator в сценарии VBScript нужно вызвать функцию CreateObject() и указать в качестве ее аргумента программный идентификатор WbemScripting.SWbemLocator, например:

Set objSWbemLocator = CreateObject
 ("WbemScripting.SWbemLocator")

Единственный имеющийся у SWbemLocator метод ConnectServer позволяет подключиться к службе WMI на указанном компьютере и получить ссылку на соответствующий объект SWbemServices. Имя компьютера, с которым следует произвести соединение, указывается в качестве первого параметра этого метода, а имя пространства имен WMI — в качестве второго. Например, чтобы подключиться к пространству имен Root\CIMV2 на компьютере POPOV, в сценарии следует выполнить следующие строки:

Set objLocator = CreateObject
  ("WbemScripting.SWbemLocator")
Set objService = objLocator.ConnectServer
  ("POPOV", "Root\CIMV2")

При этом будет произведена попытка соединения от имени текущей учетной записи. В качестве третьего и четвертого параметров метода ConnectServer можно при необходимости указать имя пользователя и пароль для связи с нужным пространством имен. Например, для подключения к пространству имен Root\CIMV2 на компьютере POPOV от имени учетной записи Popov домена Domain1 с паролем MyPassword, в сценарии следует выполнить следующие строки:

Set objLocator = CreateObject
  ("WbemScripting.SWbemLocator")
Set objService = objLocator.ConnectServer
 ("POPOV", "Root\CIMV2", "Domain1\Popov", "MyPassword")

Естественно, можно не указывать явно пароль в тексте сценария, а вводить его с клавиатуры в какую-либо переменную, которую затем подставить в метод ConnectServer. Напомним, что для ввода строки с клавиатуры в консольном режиме выполнения сценариев используются стандартные входной и выходной потоки WScript.StdIn и WScript.StdOut, а в графическом режиме — функция InputBox() языка VBScript. Кроме этого, в Windows XP и Windows Server 2003 имеется объект ScriptPW, позволяющий выполнять ввод текста с клавиатуры в консольном режиме без дублирования вводимых символов на экране. В листинге 12.1 приведен сценарий InputPassw.vbs (запускать этот сценарий нужно обязательно с помощью cscript.exe), в котором запрашивается пароль пользователя и производится соединение со службой WMI на удаленном компьютере с использованием этого пароля, после чего на экран выводится описание роли компьютера в домене (при этом сам введенный пароль на экране не отображается).

'*******************************************************************
' Имя: InputPassw.vbs
' Язык: VBScript
' Описание: Ввод пароля без отображения на экране для соединения 
'           с WMI на удаленном компьютере
'*******************************************************************
Option Explicit
 
' Объявляем переменные
Dim strComputer       ' Имя компьютера
Dim strNamespace      ' Имя пространства имен
Dim strClass          ' Имя класса 
Dim strUser           ' Имя пользователя 
Dim strPassw          ' Пароль пользователя 
Dim objPassw          ' Объект ScriptPW
Dim objLocator        ' Объект SWbemLocator
Dim objService        ' Объект SWbemServices
Dim colInstances      ' Коллекция экземпляров класса WMI
Dim objInstance       ' Элемент коллекции
Dim strComputerRole   ' Роль компьютера в домене

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "POPOV"
strNamespace = "Root\CIMV2"
strClass = "Win32_ComputerSystem"
strUser = "POPOV\404_Popov"

'Создаем объект ScriptPW
Set objPassw = CreateObject("ScriptPW.Password")
' Выводим подсказку для ввода пароля
WScript.StdOut.Write "Введите пароль для " & strUser & ": "
'Вводим пароль
strPassw = objPassw.GetPassword()

'Создаем объект SWbemLocator
Set objLocator = CreateObject("WbemScripting.SWbemLocator")
'Соединяемся с пространством имен WMI от имени заданной учетной записи
Set objService = objLocator.ConnectServer(strComputer, strNamespace, strUser, strPassw)

' Создаем коллекцию экземпляров класса Win32_ComputerSystem
Set colInstances = objService.InstancesOf(strClass)

' Перебираем элементы коллекции 
For Each objInstance In colInstances
    ' Определяем описание роли
    Select Case objInstance.DomainRole 
        Case 0 
            strComputerRole = "Standalone Workstation"
        Case 1        
            strComputerRole = "Member Workstation"
        Case 2
            strComputerRole = "Standalone Server"
        Case 3
            strComputerRole = "Member Server"
        Case 4
            strComputerRole = "Backup Domain Controller"
        Case 5
            strComputerRole = "Primary Domain Controller"
    End Select
    
    ' Выводим результат на экран
    Wscript.Echo "Роль компьютера " & strComputer & ": " & strComputerRole
Next
'************************* Конец ***********************************
Листинг 12.1. Ввод пароля без отображения на экране для соединения с WMI на удаленном компьютере (html, txt)
Соединение посредством моникера WMI

Альтернативным вариантом получения доступа к подсистеме WMI на локальном или удаленном компьютере является использование WMI-моникеров. Понятие моникер относится к COM-объектам, где под этим термином понимается строка (отображаемое имя, display name ), задающая путь к объекту, экземпляр которого должен быть создан в клиентском приложении. В контексте сценариев VBScript моникер WMI — это строка определенной структуры, передаваемая в качестве параметра функции GetObject, в результате выполнения которой возвращается ссылка на определенный объект или конкретный экземпляр объекта библиотеки поддержки сценариев WMI.

Например, можно задать WMI-моникер, извлекающий, как и при использовании метода ConnectServer объекта SWbemLocator, ссылку на объект SWbemServices. Можно построить моникер, обеспечивающий доступ к объекту SWbemObjectSet, содержащему набор объектов WMI. Наконец, с помощью моникера можно получить ссылку на конкретный экземпляр объекта SWbemObject.

Такая гибкость делает WMI-моникеры очень полезными для упрощения структуры сценария, однако следует иметь в виду следующие ограничения при работе с моникерами:

Формат строки WMI-моникера похож на стандартный путь к объектам WMI. При этом моникеры могут состоять из трех частей:

Рассмотрим каждую из частей моникера более подробно.

Префикс "WinMgmts:"

Все моникеры WMI должны начинаться со строки "WinMgmts:", причем регистр символов здесь неважен, т. е. в сценарии можно писать "winmgmts:", "WINMGMTS:" и т. д. Самый простой WMI-моникер совпадает с этой строкой, позволяя получить доступ к пространству имен по умолчанию на локальном компьютере (как правило, таким пространством является Root\CIMV2):

Set objService = GetObject("WinMgmts:")

В переменной objService после выполнения этой строки сценария будет храниться ссылка на объект SWbemServices, причем методы объекта SWbemServices можно вызывать в той же строке, в которой записан моникер, например:

Set colProcess = GetObject("WinMgmts:").InstancesOf("Win32_Process")

Естественно, того же результата (формирование коллекции всех запущенных в системе процессов), можно добиться с помощью двух строк:

Set objService = GetObject("WinMgmts:")
Set colProcess = objService.InstancesOf("Win32_Process")

Если перед нами стоит задача перебора коллекции, построенной с помощи WMI-моникера, то функцию GetObject() можно использовать внутри цикла For Each … In. Например, для вывода на экран названий всех процессов, запущенных в системе, достаточно выполнить сценарий, состоящий всего из трех строк:

For Each objProcess In GetObject("WinMgmts:")
objService.InstancesOf("Win32_Process")
  WScript.Echo objProcess.Name
Next

Связь WMI-моникера "WinMgmts:" с библиотекой поддержки сценариев WMI осуществляется с помощью раздела HKEY_CLASSES_ROOT\WINMGMTS, в подразделе CLSID которого записан идентификатор, указывающий, в свою очередь, на раздел HKEY_CLASSES_ROOT\CLSID\{172BDDF8-CEEA-11D1-8B05-00600806D9B6}. Раздел же HKEY_CLASSES_ROOT\CLSID\{172BDDF8-CEEA-11D1-8B05-00600806D9B6} содержит подраздел InProcserver32, значением которого по умолчанию является полный путь к файлу wbemdisp.dll, содержащему библиотеку поддержки сценариев WMI и реализующему объект SWbemServices.

Настройки безопасности в моникере

После префикса "WinMgmts:" в моникере WMI можно указать следующие параметры безопасности, которые будут применяться при работе с подсистемой WMI:

Замечание

Смысл и значение параметров, задающих уровень олицетворения и проверки подлинности DCOM, был объяснен ранее в разделе "Безопасность при работе с WMI" лекции 10.

Параметр authority определяет протокол безопасности (NT LAN Manager — NTLM, или Kerberos), который будет использоваться WMI при выполнении проверки подлинности. В случае NTLM в качестве значения параметра authority задается ключевое слово NTLMDomain и имя нужного домена, например:

"WinMgmts:{authority=NTLMDomain:Domain1}"

Для перехода к Kerberos в моникере указыватся ключевое слово Kerberos и путь к нужному серверу, например:

"WinMgmts:{authority=Kerberos:Domain1\Server1}"

Замечание

Параметр authority нельзя указывать в WMI-моникерах, устанавливающих связь с подсистемой WMI на локальном компьютере.

Последняя составная часть параметров безопасности в строке WMI-моникера позволяет назначать и отменять привилегии, необходимые для выполнения определенных задач (например, для удаленного выключения рабочей станции). Для того чтобы назначить ту или иную привилегию сценарию, нужно указать имя этой привилегии в списке. Для отмены привилегии перед ее именем ставится восклицательный знак (!). С помощью моникера WMI можно назначить или отменить следующие привилегии: CreateToken, PrimaryToken, LockMemory, IncreaseQuota, MachineAccount, Tcb, Security, TakeOwnership, LoadDriver, SystemProfile, SystemTime, ProfileSingleProcess, IncreaseBasePriority, CreatePagefile, CreatePermanent, Backup, Restore, ShutDown, Debug, Audit, SystemEnvironment, ChangeNotify, RemoteShutDown, Udock, SyncAgent и EnableDelegation.

Все параметры безопасности в строке WMI-моникера следуют непосредственно за префиксом "WinMgmts:" и заключаются в фигурные скобки. Несколько параметров следует разделять запятыми, например:

"WinMgmts:{impersonationLevel=Impersonate, 
 authenticationLevel=pktPrivacy,authority=NTLMDomain:Domain1}"

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

"WinMgmts:{impersonationLevel=Impersonate, authenticationLevel=pktPrivacy, 
  (Shutdown, !RemoteShutdown)}"
Путь к объекту WMI в моникере

Напомним сначала, что любой класс или экземпляр класса WMI определяется путем к объекту WMI, который может состоять из сетевого имени компьютера, имени пространства имен, имени класса и набора ключевых свойств объекта вместе с их значениями (см. разд. "Путь к классам и объектам CIM" лекции 10).

Для получения с помощью моникера WMI ссылки на нужный объект WMI, нужно в качестве третьего параметра WMI-моникера указать путь к данному объекту. При этом формат строки моникера зависит от наличия в ней параметров безопасности.

Если параметры безопасности указаны, то путь к объекту следует за закрывающей скобкой параметров безопасности и отделяется от нее восклицательным знаком. Например, следующий моникер будет в сценарии определять путь к экземпляру класса Win32_Service, у которого в ключевом свойстве Name записана строка Alerter, и который расположен в пространстве CIMV2 на компьютере с именем POPOV:

"WinMgmts:{impersonationLevel=Impersonate}!\\POPOV\Root\CIMV2:
  Win32_Service.Name='Alerter'"

Если же параметры безопасности в моникере опущены, то путь к объекту записывается после двоеточия в префиксе "WinMgmts:" без восклицательного знака:

"WinMgmts:\\POPOV\Root\CIMV2:Win32_Service.Name='Alerter'"

Замечание

Для правильной идентификации объектов в пути к ним должны указываться имена и значения ключевых свойств (например, в классе Win32_Service таковым является свойство Name, а в классе Win32_Process — свойство Handle). Для того чтобы узнать, какое свойство у класса является ключевым, можно воспользоваться тестером WMI (wbemtest.exe) или утилитой WMI CIM Studio.

В принципе, в WMI-моникере можно указывать не полный путь к объекту, а лишь нужные фрагменты, например "WinMgmts:\Root\CIMV2", "WinMgmts:\\POPOV" и т. п. При этом если опущено имя компьютера или вместо него стоит точка (.), то будет производиться обращение к подсистеме WMI локального компьютера. Если опущено пространство имен, то WMI будет работать с пространством имен по умолчанию, которое извлекается из подраздела HKEY_LOCAL_MACHINE\SOFTWARE\ Microsoft\WBEM\Scripting\Default Namespace системного реестра рабочей станции, к которой производится обращение.

Замечание

Рекомендуется в WMI-моникере всегда явно указывать нужное пространство имен WMI, не полагаясь на значение, которое хранится в реестре.

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

Лекция 13. Типичные администраторские сценарии WMI

Разбираются примеры сценариев WMI, связанных с повседневной работой администратора операционной системы (управление процессами и службами, сбор и анализ системной информации, инвентаризация оборудования, перезагрузка и выключение рабочих станций)

Типичные администраторские сценарии WMI

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

Управление компьютером

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

Завершение сеанса пользователя

Для завершения сеанса активного пользователя необходимо вызвать метод Win32Shutdown объекта Win32_OperatingSystem (листинг 13.1).

'*******************************************************************
' Имя: LogOff.vbs
' Язык: VBScript
' Описание: Завершение сеанса пользователя  
'*******************************************************************
Option Explicit
 
' Объявляем переменные
Dim strComputer       ' Имя компьютера
Dim strNamespace      ' Имя пространства имен
Dim strClass          ' Имя класса 
Dim objClass          ' Объект SWbemObject (класс WMI)
Dim colInstances      ' Коллекция экземпляров класса WMI
Dim objInstance       ' Элемент коллекции

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"
strClass = "Win32_OperatingSystem"

' Получаем указатель на класс WMI
Set objClass = GetObject("WinMgmts:\\" & strComputer & _
                         "\" & strNamespace & ":" & strClass)
' Создаем коллекцию экземпляров класса Win32_OperatingSystem
Set colInstances = objClass.Instances_

' Перебираем элементы коллекции 
For Each objInstance In colInstances
  ' Выводим на экран предупреждение
  WScript.Echo "На компьютере " &  objInstance.CSNAME & VbCrLf &_
               "сеанс текущего пользователя будет завершен "  
  ' Для каждого экземпляра вызываем метод Win32Shutdown
  objInstance.Win32Shutdown(0)      
Next
'************************* Конец ***********************************
Листинг 13.1. Завершение сеанса пользователя (html, txt)
Перезагрузка компьютера

Для перезагрузки компьютера необходимо использовать метод Reboot объекта Win32_OperatingSystem (листинг 13.2). При этом при подключении к подсистеме WMI необходимо указать дополнительные привилегии Shutdown (для перезагрузки локального компьютера) и RemoteShutdown (для перезагрузки удаленного компьютера).

'*******************************************************************
' Имя: Reboot.vbs
' Язык: VBScript
' Описание: Перезагрузка компьютера
'*******************************************************************
Option Explicit
 
' Объявляем переменные
Dim strComputer       ' Имя компьютера
Dim strNamespace      ' Имя пространства имен
Dim strClass          ' Имя класса 
Dim objClass          ' Объект SWbemObject (класс WMI)
Dim colInstances      ' Коллекция экземпляров класса WMI
Dim objInstance       ' Элемент коллекции

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"
strClass = "Win32_OperatingSystem"

' Получаем указатель на класс WMI
Set objClass = GetObject("WinMgmts:{(Shutdown,RemoteShutdown)}!\\" &_ 
               strComputer & "\" & strNamespace & ":" & strClass)
' Создаем коллекцию экземпляров класса Win32_OperatingSystem
Set colInstances = objClass.Instances_

' Перебираем элементы коллекции 
For Each objInstance In colInstances
  ' Выводим на экран предупреждение
  WScript.Echo "Компьютер " &  objInstance.CSNAME &_
               " будет перезагружен "  
  ' Для каждого экземпляра вызываем метод Reboot
  objInstance.Reboot()
Next
'************************* Конец ***********************************
Листинг 13.2. Перезагрузка компьютера (html, txt)
Выключение компьютера

В сценарии Shutdown.vbs (листинг 13.3) кроме непосредственного выключения компьютера (метод Shutdown объекта Win32_OperatingSystem ) с помощью средств языка VBScript реализована обработка возможных ошибок.

'*******************************************************************
' Имя: Shutdown.vbs
' Язык: VBScript
' Описание: Выключение компьютера
'*******************************************************************
Option Explicit
On Error Resume Next
 
' Объявляем переменные
Dim strComputer       ' Имя компьютера
Dim strNamespace      ' Имя пространства имен
Dim strClass          ' Имя класса 
Dim objClass          ' Объект SWbemObject (класс WMI)
Dim colInstances      ' Коллекция экземпляров класса WMI
Dim objInstance       ' Элемент коллекции
Dim iAnswer           ' Код возврата функции MsgBox

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"
strClass = "Win32_OperatingSystem"

' Получаем указатель на класс WMI 
Set objClass = GetObject("WinMgmts:{(Shutdown,RemoteShutdown)}!\\" & strComputer & _
                         "\" & strNamespace & ":" & strClass)
' Создаем коллекцию экземпляров класса Win32_OperatingSystem
Set colInstances = objClass.Instances_

' Перебираем элементы коллекции 
For Each objInstance In colInstances
  ' Выводим на экран предупреждение
  iAnswer = MsgBox("Выключить компьютер " & objInstance.CSNAME & " ?", _
                  vbQuestion + vbOKCancel, "Внимание!")

  If iAnswer = vbOK Then 
    ' Выводим сообщение о перезагрузке
    WScript.Echo "Компьютер " &  objInstance.CSNAME & " будет выключен"  
    ' Вызываем метод Shutdown
    objInstance.Shutdown()

    If Err.number <> 0 Then
      WScript.Echo  "Номер ошибки: " & Err.Number & vbNewLine & _
                    "Описание: " & Err.Description
    End If
  Else 
    ' Выводим сообщение об отмене операции
    WScript.Echo  "Не будем пока выключать"
  End if
Next
'************************* Конец ***********************************
Листинг 13.3. Выключение компьютера (html, txt)

Получение и анализ системной информации

Листинги 13.4–13.7 содержат сценарии, позволяющие получить информацию об операционной системе (серийный номер, номер сборки, номер последнего обновления, дата установки, кодовая страница, список команд, которые выполняются автоматически при старте системы, и т. д.) и о BIOS компьютера (производитель, серийный номер, номер сборки и т. д.).

Вывод информации о BIOS

В сценарии BIOSInfo.vbs (листинг 13.4) на экран выводятся некоторые свойства объекта Win32_BIOS, в котором хранятся параметры и характеристики BIOS, установленной на компьютере.

'*******************************************************************
' Имя: BIOSInfo.vbs
' Язык: VBScript
' Описание: Вывод информации о BIOS
'*******************************************************************
Option Explicit
 
' Объявляем переменные
Dim strComputer       ' Имя компьютера
Dim strNamespace      ' Имя пространства имен
Dim strClass          ' Имя класса 
Dim objClass          ' Объект SWbemObject (класс WMI)
Dim colInstances      ' Коллекция экземпляров класса WMI
Dim objBIOS           ' Элемент коллекции
Dim strResult         ' Результирующая строка

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"
strClass = "Win32_BIOS"
strResult = "Информация о BIOS :" & VbCrLf

' Получаем указатель на класс WMI 
Set objClass = GetObject("winmgmts:\\" & strComputer & _
                         "\" & strNamespace & ":" & strClass)
' Создаем коллекцию экземпляров класса Win32_BIOS
Set colInstances = objClass.Instances_

' Перебираем элементы коллекции 
For Each objBIOS in colInstances
  strResult = strResult & "Name: " & objBIOS.Name & VbCrLf
  strResult = strResult & "Manufacturer: " & objBIOS.Manufacturer &_
     VbCrLf
  strResult = strResult & "Caption: " & objBIOS.Caption & VbCrLf
  strResult = strResult & "Description: " & objBIOS.Description & VbCrLf    
  strResult = strResult & "Build Number: " & objBIOS.BuildNumber & VbCrLf
  strResult = strResult & "Current Language: " & objBIOS.CurrentLanguage & VbCrLf
  strResult = strResult & _
   "Installable Languages: " & objBIOS.InstallableLanguages & VbCrLf
  strResult = strResult & "Primary BIOS: " & objBIOS.PrimaryBIOS & VbCrLf
  strResult = strResult & "Release Date: " & objBIOS.ReleaseDate & VbCrLf
  strResult = strResult & "Serial Number: " & objBIOS.SerialNumber & VbCrLf
  strResult = strResult & "SMBIOS Version: " & _
    objBIOS.SMBIOSBIOSVersion & VbCrLf
  strResult = strResult & _
    "SMBIOS Major Version: " & objBIOS.SMBIOSMajorVersion & VbCrLf
  strResult = strResult & _
    "SMBIOS Minor Version: " & objBIOS.SMBIOSMinorVersion & VbCrLf
  strResult = strResult & "SMBIOS Present: " & objBIOS.SMBIOSPresent _
    & VbCrLf
  strResult = strResult & "Status: " & objBIOS.Status & VbCrLf
  strResult = strResult & "Version: " & objBIOS.Version & VbCrLf
Next

'Выводим строку на экран
Wscript.Echo strResult
'************************* Конец ***********************************
Листинг 13.4. Вывод информации о BIOS (html, txt)
Вывод списка команд, выполняемых при загрузке системы

Все команды, которые выполняются автоматически при старте системы, хранятся в WMI в виде экземпляров класса Win32_StartupCommand. Сценарий StartupCommand.vbs, представленный в листинге 13.5, выводит эти команды на экран.

'*******************************************************************
' Имя: StartupCommand.vbs
' Язык: VBScript
' Описание: Вывод списка команд, выполняемых при загрузке компьютера
'*******************************************************************
Option Explicit
 
' Объявляем переменные
Dim strComputer       ' Имя компьютера
Dim strNamespace      ' Имя пространства имен
Dim strClass          ' Имя класса 
Dim objClass          ' Объект SWbemObject (класс WMI)
Dim colStartupCommands' Коллекция экземпляров класса WMI
Dim objStartupCommand ' Элемент коллекции
Dim strResult         ' Строка для вывода на экран

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"
strClass = "Win32_StartupCommand"
strResult = "Комманды выполняемые при загрузке компьютера :" & VbCrLf

' Получаем указатель на класс WMI 
Set objClass = GetObject("WinMgmts:\\" & strComputer & _
                         "\" & strNamespace & ":" & strClass)
' Создаем коллекцию экземпляров класса Win32_StartupCommand
Set colStartupCommands = objClass.Instances_

' Перебираем элементы коллекции 
For Each objStartupCommand in colStartupCommands
  strResult = strResult & objStartupCommand.Command & VbCrLf  
Next

' Выводим результат на экран
Wscript.Echo strResult
'************************* Конец ***********************************
Листинг 13.5. Определение команд, выполняемых при загрузке компьютера (html, txt)
Вывод свойств операционной системы

Основные свойства установленной операционной системы (загрузочное устройство, номер сборки, дата установки и т. д.) можно получить с помощью объекта Win32_OperatingSystem (листинг 13.6).

'*******************************************************************
' Имя: OSProperty.vbs
' Язык: VBScript
' Описание: Вывод свойств операционной системы
'*******************************************************************
Option Explicit
 
' Объявляем переменные
Dim strComputer        ' Имя компьютера
Dim strNamespace       ' Имя пространства имен
Dim strClass           ' Имя класса 
Dim objClass           ' Объект SWbemObject (класс WMI)
Dim colOperatingSystems' Коллекция экземпляров класса WMI
Dim objOperatingSystem ' Элемент коллекции
Dim strResult          ' Строка для вывода на экран

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"
strClass = "Win32_OperatingSystem"
strResult = " Свойства операционной системы: " & VbCrLf & VbCrLf

' Получаем указатель на класс WMI 
Set objClass = GetObject("WinMgmts:\\" & strComputer & _
                         "\" & strNamespace & ":" & strClass)
' Создаем коллекцию экземпляров класса Win32_OperatingSystem
Set colOperatingSystems = objClass.Instances_

' Перебираем элементы коллекции 
For Each objOperatingSystem in colOperatingSystems
  ' Формирум строку для вывода на экран 
  strResult = strResult & "Boot Device: " & _ 
              objOperatingSystem.BootDevice & VbCrLf
  strResult = strResult & "Build Number: " & _
              objOperatingSystem.BuildNumber & VbCrLf 
  strResult = strResult & "Build Type: " & _
              objOperatingSystem.BuildType & VbCrLf
  strResult = strResult & "Caption: " & _
              objOperatingSystem.Caption & VbCrLf
  strResult = strResult & "Code Set: " & _
              objOperatingSystem.CodeSet & VbCrLf
  strResult = strResult & "Country Code: " & _
              objOperatingSystem.CountryCode & VbCrLf
  strResult = strResult & "Install Date: " & _
              objOperatingSystem.InstallDate & VbCrLf
  strResult = strResult & "Licensed Users: " & _
              objOperatingSystem.NumberOfLicensedUsers & VbCrLf
  strResult = strResult & "Organization: " & _
              objOperatingSystem.Organization & VbCrLf
  strResult = strResult & "OS Language: " & _
              objOperatingSystem.OSLanguage & VbCrLf
  strResult = strResult & "OS Product Suite: " & _
              objOperatingSystem.OSProductSuite & VbCrLf
  strResult = strResult & "OS Type: " & _
              objOperatingSystem.OSType & VbCrLf
  strResult = strResult & "Primary: " & _
              objOperatingSystem.Primary & VbCrLf
  strResult = strResult & "Registered User: " & _
              objOperatingSystem.RegisteredUser & VbCrLf
  strResult = strResult & "Serial Number: " & _
              objOperatingSystem.SerialNumber & VbCrLf
  strResult = strResult & "Version: " & _
              objOperatingSystem.Version & VbCrLf
Next

' Выводим результат на экран
Wscript.Echo strResult
'************************* Конец ***********************************
Листинг 13.6. Вывод свойств операционной системы (html, txt)
Определение номера последнего обновления, установленного на компьютере

Сценарий ServPack.vbs, приведенный в листинге 13.7, выводит на экран номер последнего обновления (ServicePack), которое было установлено на компьютере (свойства ServicePackMajorVersion и ServicePackMinorVersion объекта Win32_OperatingSystem ).

'*******************************************************************
' Имя: ServPack.vbs
' Язык: VBScript
' Описание: Вывод номера ServicePack для операционной системы
'*******************************************************************
Option Explicit
 
' Объявляем переменные
Dim strComputer         ' Имя компьютера
Dim strNamespace        ' Имя пространства имен
Dim strClass            ' Имя класса 
Dim objClass            ' Объект SWbemObject (класс WMI)
Dim colOperatingSystems ' Коллекция экземпляров класса WMI
Dim objOperatingSystem  ' Элемент коллекции
Dim strResult           ' Строка для вывода на экран

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"
strClass = "Win32_OperatingSystem"
strResult = "ServicePack установленный на этом компьютере " & VbCrLf

' Получаем указатель на класс WMI 
Set objClass = GetObject("WinMgmts:\\" & strComputer & _
                         "\" & strNamespace & ":" & strClass)
' Создаем коллекцию экземпляров класса Win32_OperatingSystem
Set colOperatingSystems = objClass.Instances_

' Перебираем элементы коллекции 
For Each objOperatingSystem in colOperatingSystems
  ' Формируем строку для вывода на экран
  strResult = strResult & "№ " & _ 
              objOperatingSystem.ServicePackMajorVersion & "." &_
              objOperatingSystem.ServicePackMinorVersion & VbCrLf  
Next

' Выводим результирущую строку на экран
Wscript.Echo strResult
'************************* Конец ***********************************
Листинг 13.7. Определение номера последнего обновления (html, txt)

Сбор сведений о подключенных устройствах

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

Получение информации о физической памяти

Получить информацию о банках физической памяти компьютера позволяют экземпляры класса Win32_PhysicalMemory. Сценарий MemoryInfo.vbs (листинг 13.8) выводит на экран наиболее важные свойства этих экземпляров.

'*******************************************************************
' Имя: MemoryInfo.vbs
' Язык: VBScript
' Описание: Вывод информации о физической памяти
'*******************************************************************
Option Explicit

' Объявляем переменные
Dim strComputer       ' Имя компьютера
Dim strNamespace      ' Имя пространства имен
Dim strClass          ' Имя класса 
Dim objClass          ' Объект SWbemObject (класс WMI)
Dim colPhysMemory     ' Коллекция экземпляров класса WMI
Dim objPhysMemory     ' Элемент коллекции
Dim strResult         ' Результирующая строка

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"
strClass = "Win32_PhysicalMemory"
strResult = "Информация о физической памяти:" & vbCrLf & vbCrLf

' Получаем указатель на класс WMI 
Set objClass = GetObject("WinMgmts:\\" & strComputer & _
                         "\" & strNamespace & ":" & strClass)
' Создаем коллекцию экземпляров класса Win32_PhysicalMemory
Set colPhysMemory = objClass.Instances_

' Перебираем коллекцию
For Each objPhysMemory In colPhysMemory
  strResult = strResult & "Bank Label: " & _
              objPhysMemory.BankLabel & VbCrLf
  strResult = strResult & "Capacity: " & _
              objPhysMemory.Capacity & VbCrLf
  strResult = strResult & "Data Width: " & _
              objPhysMemory.DataWidth & VbCrLf
  strResult = strResult & "Description: " & _
              objPhysMemory.Description & VbCrLf
  strResult = strResult & "Device Locator: " & _
              objPhysMemory.DeviceLocator & VbCrLf
  strResult = strResult & "Form Factor: " & _
              objPhysMemory.FormFactor & VbCrLf
  strResult = strResult & "Hot Swappable: " & _
              objPhysMemory.HotSwappable & VbCrLf
  strResult = strResult & "Manufacturer: " & _
              objPhysMemory.Manufacturer & VbCrLf
  strResult = strResult & "Memory Type: " & _
              objPhysMemory.MemoryType & VbCrLf
  strResult = strResult & "Name: " & _
              objPhysMemory.Name & VbCrLf
  strResult = strResult & "Part Number: " & _
              objPhysMemory.PartNumber & VbCrLf
  strResult = strResult & "Speed: " & _
              objPhysMemory.Speed & VbCrLf
  strResult = strResult & "Tag: " & _
              objPhysMemory.Tag & VbCrLf
  strResult = strResult & "Type Detail: " & _
              objPhysMemory.TypeDetail & VbCrLf
Next

' Выводим результат на экран
Wscript.Echo strResult
'************************* Конец ***********************************
Листинг 13.8. Вывод информации о физической памяти (html, txt)
Получение информации о сетевом адаптере

В сценарии NetworkAdapterInfo.vbs (листинг 13.9) свойства сетевых адаптеров извлекаются с помощью класса Win32_NetworkAdapter. Отметим, что с помощью сценариев WMI можно также изменять конфигурацию сетевых карт — для этого следует использовать класс Win32_NetworkAdapterConfiguration, который предоставляет множество методов для настройки сетевых служб DNS, DHCP, WINS.

'*******************************************************************
' Имя: NetworkAdapterInfo.vbs
' Язык: VBScript
' Описание: Вывод информации о сетевых адаптерах
'*******************************************************************
Option Explicit

' Объявляем переменные
Dim strComputer         ' Имя компьютера
Dim strNamespace        ' Имя пространства имен
Dim objService          ' Объект SWbemServices    
Dim colNetworkAdapters  ' Коллекция экземпляров класса WMI
Dim objNetworkAdapter   ' Элемент коллекции
Dim strResult           ' Результирующая строка
Dim WshShell            ' Объект WshShell
Dim theNotepad          ' Объект WshScriptExec

' Объявляем константы
Const wbemFlagForwardOnly = 32
Const wbemFlagReturnImmediately = 16
Const ForWriting = 2

' Процедура для записи информации в файл 
Sub TextOut (Text, File)
  ' Объявляем переменные
  Dim  objFSO, FOut 
  ' Создаем объект FileSystemObject
  Set  objFSO=WScript.CreateObject("Scripting.FileSystemObject")
  ' Открываем выходной файл для записи
  Set  FOut = objFSO.OpenTextFile (File,ForWriting,true)
  ' Записываем текстовую строку в файл
  FOut.WriteLine Text
  ' Закрываем выходной файл
  FOut.Close
End Sub

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"
strResult = "Зарегистрированные сетевые адаптеры " & VbCrLf & VbCrLf

' Подключаемся к пространству имен WMI
Set objService = GetObject("WinMgmts:\\" & _
                                   strComputer & "\" & strNamespace)

Set colNetworkAdapters = objService.ExecQuery(_
                         "SELECT * FROM Win32_NetworkAdapter",,_
                         wbemFlagReturnImmediately+wbemFlagForwardOnly)

' Перебираем элементы коллекции 
For Each objNetworkAdapter In colNetworkAdapters
  strResult = strResult & "Adapter Type: " & _
    objNetworkAdapter.AdapterType & VbCrLf &_
    "Description: " & objNetworkAdapter.Description & vbCrLf &_
    "Installed: " & objNetworkAdapter.Installed & vbCrLf &_
    "Manufacturer: " & objNetworkAdapter.Manufacturer & vbCrLf &_
    "Product Name: " & objNetworkAdapter.ProductName & vbCrLf &_
    "Net Connection ID: " & objNetworkAdapter.NetConnectionID & vbCrLf &_
    "Net Connection Status: " & _
      objNetworkAdapter.NetConnectionStatus & vbCrLf & _
    "MAC Address: " & objNetworkAdapter.MACAddress & vbCrLf &_  
    "PNP Device ID" & objNetworkAdapter.PNPDeviceID
Next

' Выводим результат в текстовый файл
TextOut  strResult, "C:\NetworkAdapters.txt" 

'Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
'Открываем созданный файл в Блокноте
Set theNotepad = WshShell.Exec("notepad " & "C:\NetworkAdapters.txt" )
'************************* Конец ***********************************
Листинг 13.9. Вывод информации о сетевых адаптерах (html, txt)

Управление службами и процессами

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

Получение информации о свойствах и состоянии служб

Сценарий ServicesInfo.vbs, приведенный в листинге 13.10, выводит информацию о зарегистрированных службах (экземпляры класса Win32_Service ) в текстовый файл C:\Services.txt, который затем открывается с помощью Блокнота.

'*******************************************************************
' Имя: ServicesInfo.vbs
' Язык: VBScript
' Описание: Вывод информации о службах 
'*******************************************************************
Option Explicit

' Объявляем переменные
Dim strComputer       ' Имя компьютера
Dim strNamespace      ' Имя пространства имен
Dim objWMIService     ' Объект SWbemServices    
Dim colServices       ' Коллекция экземпляров класса WMI
Dim objService        ' Элемент коллекции
Dim strResult         ' Результирующая строка
Dim WshShell          ' Объект WshShell
Dim theNotepad        ' Объект WshScriptExec

' Объявляем константы
Const wbemFlagForwardOnly = 32
Const wbemFlagReturnImmediately = 16
Const ForWriting = 2

' Функция для записи информации в файл 
Sub TextOut (Text, File)
  ' Объявляем переменные
  Dim  objFSO, FOut 
  ' Создаем объект FileSystemObject
  Set  objFSO=WScript.CreateObject("Scripting.FileSystemObject")
  ' Открываем выходной файл для записи
  Set  FOut = objFSO.OpenTextFile (File,ForWriting,true)
  ' Записываем текстовую строку в файл
  FOut.WriteLine Text
  ' Закрываем выходной файл
  FOut.Close
End Sub

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"
strResult = "Информация о службах " & VbCrLf & VbCrLf

' Подключаемся к пространству имен WMI
Set objWMIService = GetObject("WinMgmts:\\" & _
                                   strComputer & "\" & strNamespace)

Set colServices = objWMIService.ExecQuery("SELECT * FROM Win32_Service"_
                  ,, wbemFlagReturnImmediately+wbemFlagForwardOnly)
For Each objService In colServices
  strResult = strResult & "Name: " & _
              objService.Name & VbCrLf
  strResult = strResult & "Display Name: " & _
              objService.DisplayName & VbCrLf
  strResult = strResult & "Caption: " & _
              objService.Caption & VbCrLf
  strResult = strResult & "Description: " & _
              objService.Description & VbCrLf
  strResult = strResult & "Path Name: " & _
              objService.PathName & VbCrLf
  strResult = strResult & "ServiceType: " & _
              objService.ServiceType & VbCrLf
  strResult = strResult & "Status: " & _
              objService.Status & VbCrLf
  strResult = strResult & "State: " & _
              objService.State & VbCrLf
  strResult = strResult & "Started: " & _
              objService.Started & VbCrLf
  strResult = strResult & "Start Mode: " & _
              objService.StartMode & VbCrLf
  strResult = strResult & "Start Name: " & _
              objService.StartName & VbCrLf
  strResult = strResult & "Accept pause: " & _
              objService.AcceptPause & VbCrLf
  strResult = strResult & "Accept stop: " & _
              objService.AcceptStop & VbCrLf
  strResult = strResult & "********************************" & VbCrLf &_
              VbCrLf
Next

' Выводим результат в текстовый файл
TextOut  strResult, "C:\Services.txt" 

'Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
'Открываем созданный файл в Блокноте
Set theNotepad = WshShell.Exec("notepad " & "C:\Services.txt" )
'************************* Конец ***********************************
Листинг 13.10. Вывод информации о всех службах Windows (html, txt)
Запуск и восстановление работы служб

В сценарии StartStoppedServices.vbs, описанном в листинге 13.11, производится запуск всех остановленных служб (с состоянием Stopped), которые должны стартовать автоматически при запуске системы.

'*******************************************************************
' Имя: StartStoppedServices.vbs
' Язык: VBScript
' Описание: Запуск остановленных служб 
'*******************************************************************
Option Explicit

' Объявляем переменные
Dim strComputer       ' Имя компьютера
Dim strNamespace      ' Имя пространства имен
Dim objWMIService     ' Объект SWbemServices    
Dim colServices       ' Коллекция экземпляров класса WMI
Dim objService        ' Элемент коллекции
Dim strResult         ' Результирующая строка
Dim WshShell          ' Объект WshShell
Dim Res               

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"

' Подключаемся к пространству имен WMI
Set objWMIService = GetObject("WinMgmts:\\" & _
                                   strComputer & "\" & strNamespace)
' Формируем коллекцию остановленных служб 
Set colServices = objWMIService.ExecQuery _
("SELECT * FROM Win32_Service WHERE State = 'Stopped' and StartMode = " _
 & "'Auto'")

' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")

' Запрос на запуск служб
Res = WshShell.Popup("Запустить все остановленные службы?",0, _
  "Работа со службами Windows",vbQuestion+vbYesNo)
If Res=vbYes Then
  ' Запускаем каждую остановленную службу         
  For Each objService In colServices
    objService.StartService()
  Next
  WScript.Echo "Все остановленные службы запущены"
End If  
'************************* Конец ***********************************
Листинг 13.11. Запуск всех остановленных служб (html, txt)

Сценарий ResumePausedServices.vbs, приведенный в листинге 13.12, восстанавливает работу всех приостановленных служб (с состоянием Paused), которые должны стартовать автоматически при запуске системы.

'*******************************************************************
' Имя: ResumePausedServices.vbs
' Язык: VBScript
' Описание: Продолжение работы приостановленных служб 
'*******************************************************************
Option Explicit

' Объявляем переменные
Dim strComputer       ' Имя компьютера
Dim strNamespace      ' Имя пространства имен
Dim objWMIService     ' Объект SWbemServices    
Dim colServices       ' Коллекция экземпляров класса WMI
Dim objService        ' Элемент коллекции
Dim strResult         ' Результирующая строка
Dim WshShell          ' Объект WshShell
Dim Res               

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"

' Подключаемся к пространству имен WMI
Set objWMIService = GetObject("WinMgmts:\\" & _
                                   strComputer & "\" & strNamespace)
' Формируем коллекцию остановленных служб 
Set colServices = objWMIService.ExecQuery _
("SELECT * FROM Win32_Service WHERE State = 'Paused' and StartMode = " _
 & "'Auto'")

' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")

' Запрос на запуск служб
Res = WshShell.Popup("Возобновить работу всех приостановленных служб?"_
  ,0, "Работа со службами Windows",vbQuestion+vbYesNo)
If Res=vbYes Then
  ' Возобновляем каждую приостановленную службу         
  For Each objService In colServices
    objService.ResumeService()
  Next
  WScript.Echo "Работа всех приостановленных служб возобновлена"
End If  
'************************* Конец ***********************************
Листинг 13.12. Продолжение работы всех приостановленных служб (html, txt)
Завершение процессов

В сценарии KillProcess.vbs, описанном в листинге 13.13, на примере Блокнота (Notepad.exe) показано, каким образом можно принудительно завершить работу запущенных процессов (для этого используется метод Terminate соответствующего объекта Win32_Process ).

'*******************************************************************
' Имя: KillProcess.vbs
' Язык: VBScript
' Описание: Завершение запущенного процесса
'*******************************************************************
Option Explicit
 
' Объявляем переменные
Dim strComputer       ' Имя компьютера
Dim strNamespace      ' Имя пространства имен
Dim objService        ' Объект SWbemServices    
Dim colProcesses      ' Коллекция экземпляров класса WMI
Dim objProcess        ' Элемент коллекции
Dim WshShell          ' Объект WshShell
Dim Res

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"

' Подключаемся к пространству имен WMI
Set objService = GetObject("WinMgmts:\\" & _
                                   strComputer & "\" & strNamespace)
'Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")

' Формируем коллекцию процессов NOTEPAD.EXE
Set colProcesses = objService.ExecQuery(_
           "SELECT * FROM Win32_Process WHERE Name='NOTEPAD.EXE'")

'Запрос на завершение работы всех Блокнотов
Res=WshShell.Popup("Завершить работу всех Блокнотов?",0,_
  "Работа с процессами",vbQuestion+vbYesNo)
' Проверяем введенное значение
If Res=vbYes Then
  'Перебираем коллекцию
  For Each objProcess in colProcesses
    ' Завершаем приложение
    objProcess.Terminate()
  Next
End If
'************************* Конец ***********************************
Листинг 13.13. Принудительное завершение запущенного процесса (html, txt)
Получение информации о процессах

Сценарий ProcessInfo.vbs, приведенный в листинге 13.14, для всех запущенных процессов (экземпляры класса Win32_Process ) выводит в текстовый файл C:\Process.txt значения некоторых наиболее важных с точки зрения администратора параметров. Сформированный файл затем открывается с помощью Блокнота.

'*******************************************************************
' Имя: ProcessInfo.vbs
' Язык: VBScript
' Описание: Вывод свойств запущенных процессов 
'*******************************************************************
Option Explicit

' Объявляем переменные
Dim strComputer       ' Имя компьютера
Dim strNamespace      ' Имя пространства имен
Dim objService        ' Объект SWbemServices    
Dim colProcesses      ' Коллекция экземпляров класса WMI
Dim objProcess        ' Элемент коллекции
Dim strResult         ' Результирующая строка
Dim WshShell          ' Объект WshShell
Dim theNotepad        ' Объект WshScriptExec

' Объявляем константы
Const wbemFlagForwardOnly = 32
Const wbemFlagReturnImmediately = 16
Const ForWriting = 2

' Функция для записи информации в файл 
Sub TextOut (Text, File)
  ' Объявляем переменные
  Dim  objFSO, FOut 
  ' Создаем объект FileSystemObject
  Set  objFSO=WScript.CreateObject("Scripting.FileSystemObject")
  ' Открываем выходной файл для записи
  Set  FOut = objFSO.OpenTextFile (File,ForWriting,true)
  ' Записываем текстовую строку в файл
  FOut.WriteLine Text
  ' Закрываем выходной файл
  FOut.Close
End Sub

'********************** Начало *************************************
' Присваиваем начальные значения переменным
strComputer = "."
strNamespace = "Root\CIMV2"
strResult = "Сведения о запущенных процессах " & VbCrLf & VbCrLf

' Подключаемся к пространству имен WMI
Set objService = GetObject("WinMgmts:\\" & _
                                   strComputer & "\" & strNamespace)

Set colProcesses = objService.ExecQuery("SELECT * FROM Win32_Process",,_
                     wbemFlagReturnImmediately+wbemFlagForwardOnly)
For Each objProcess In colProcesses
  strResult = strResult & "Name: " & objProcess.Name & VbCrLf &_
  "Description: " & objProcess.Description & VbCrLf &_
  "Handle: " & objProcess.Handle & VbCrLf &_
  "Parent Process Id: " & objProcess.ParentProcessId & VbCrLf &_
  "Command Line: " & objProcess.CommandLine & VbCrLf &_
  "Creation Date: " & objProcess.CreationDate & VbCrLf &_
  "Executable Path: " & objProcess.ExecutablePath & VbCrLf &_
  "Priority: " & objProcess.Priority & VbCrLf &_
  "Maximum WorkingSet Size: " & objProcess.MaximumWorkingSetSize & VbCrLf &_
  "Minimum WorkingSet Size: " & objProcess.MinimumWorkingSetSize & VbCrLf &_
  "Page File Usage: " & objProcess.PageFileUsage & VbCrLf &_
  "Peak Virtual Size: " & objProcess.PeakVirtualSize & VbCrLf &_
  "Peak WorkingSet Size: " & objProcess.PeakWorkingSetSize & VbCrLf &_
  "********************************" & VbCrLf & VbCrLf
Next

' Выводим результат в текстовый файл
TextOut  strResult, "C:\Process.txt" 

'Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
'Открываем созданный файл в Блокноте
Set theNotepad = WshShell.Exec("notepad " & "C:\Process.txt" )
'************************* Конец ***********************************
Листинг 13.14. Вывод свойств всех запущенных процессов (html, txt)

Лекция 14. Доступ к WMI из командной строки. Командная оболочка WMIC

Описывается командная оболочка WMI Command-line (WMIC), разработанная для работы с WMI из командной строки. Рассматривается архитектура WMIC и структура внутрених команд

Доступ к WMI из командной строки. Командная оболочка WMIC

В Windows XP и Windows Server 2003 к подсистеме WMI можно обращаться непосредственно из командной строки без помощи графических утилит и составления сложных сценариев. Для этого используется программа WMIC (WMI Command-line), которая поддерживает навигацию по информационной схеме WMI локального или удаленного компьютера, позволяя выполнять WQL-запросы к классам и объектам WMI. При этом вместо сложных названий классов WMI используются простые псевдонимы, причем можно создавать собственные псевдонимы, что делает информационную схему WMIC расширяемой.

По умолчанию WMIC поддерживает около 80 псевдонимов, с помощью которых можно выполнить 150 методов и получить значения множества свойств. Важной особенностью WMIC является то, что вывод команд может быть организован в различные форматы: на экран, в текстовый файл, в XML- и HTML-документы, в MOF-файл, в текстовый файл с разделителями или в любой другой формат, определяемый пользователем с помощью таблиц стилей XSL (eXtensible Stylesheet Language).

Одна команда WMIC может быть применена сразу к нескольким удаленным компьютерам с любой 32-разрядной версией Windows, при этом наличие WMIC на удаленной машине не требуется, необходима только установка ядра WMI и соответствующая настройка прав доступа к WMI. Кроме этого, команды WMI могут использоваться в пакетных файлах Windows, что позволяет простыми средствами автоматизировать работу с WMI на локальных или удаленных компьютерах.

В качестве недостатка WMIC можно отметить отсутствие встроенной полноценной поддержки и обработки событий WMI.

Запуск WMIC. Использование встроенной справки

С WMIC можно работать в двух режимах: интерактивном и пакетном. В интерактивном режиме с клавиатуры вводится последовательность команд WMIC, которые сразу же выполняются. Кроме этого, в интерактивном режиме удобнее работать со встроенной помощью WMIC. Пакетный режим позволяет запускать предварительно подготовленный командный (пакетный) файл с командами WMIC или выполнять из командной строки операционной системы единственную команду WMIC.

Для запуска WMIC в интерактивном режиме необходимо выполнить команду wmic в стандартном интерпретаторе команд cmd.exe или в диалоговом окне Выполнить (Run) в меню Пуск (Start). После этого на экран выводится стандартное приглашение WMIC, wmic:root\cli>.

После этого можно вводить с клавиатуры команды WMIC (регистр символов значения не имеет), которые запускаются после нажатия клавиши <Enter>. Например, если набрать в командной строке WMIC слово PROCESS и нажать <Enter>, то на экран выведется список всех процессов, запущенных в данный момент в системе:

wmic:root\cli>PROCESS
Caption          CommandLine
System Idle Process
System
smss.exe     \SystemRoot\System32\smss.exe
csrss.exe    C:\WINDOWS.1\system32\csrss.exe ObjectDirectory=.\. . .
services.exe  C:\WINDOWS.1\system32\services.exe
lsass.exe     C:\WINDOWS.1\system32\lsass.exe
svchost.exe  C:\WINDOWS.1\system32\svchost -k DcomLaunch
svchost.exe  C:\WINDOWS.1\system32\svchost -k rpcss
svchost.exe  C:\WINDOWS.1\System32\svchost.exe -k netsvcs
. . .

Если же ввести в командной строке WMIC слово OS, то мы увидим на экране свойства операционной системы, установленной на компьютере:

wmic:root\cli>OS
BootDevice               BuildNumber  BuildType          Caption
\Device\HarddiskVolume1  2600         Uniprocessor Free  Microsoft Windows . . .
Пример 14.1. (html, txt)

Естественно, это лишь самые простые примеры использования командной строки WMIC. Для того чтобы узнать о дополнительных возможностях WMIC, можно воспользоваться встроенной помощью, которая вызывается с помощью ключей /? или -?. Например, набрав один из этих ключей после слова PROCESS и нажав клавишу <Enter>, мы выведем справку, из которой, скажем, видно, что команда OS CALL позволяет выполнять некоторые действия над процессами:

wmic:root\cli>OS -?
OS - Управление установленными операционными системами.
СОВЕТ. BNF при работе с псевдонимом.
(<псевдоним> [WMI-объект] | <псевдоним> [<путь where>] | 
 [<псевдоним>] . . .
Использование:
OS ASSOC [<указатель формата>]
OS CALL <имя метода> [<список фактических параметров>]
OS CREATE <список значений>
OS DELETE
OS GET [<список свойств>] [<ключи get>]
OS LIST [<формат списка>] [<ключи>]
OS SET [<список значений>]

Выполнив теперь команду PROCESS CALL /?, мы получим краткое описание методов, которые могут быть вызваны при работе с процессами:

wmic:root\cli>PROCESS CALL /?
Вызов методов.
Использование:
CALL <имя метода> [<список фактических параметров>]
ЗАМЕЧАНИЕ. <список фактических параметров> ::= <факт. парам.> | 
  <факт. парам.>,  <
Для псевдонима доступны следующие команды и методы:
Вызов         [ Ввод/Вывод ]Параметры и тип           Состояние
====          =====================                   ======
AttachDebugger                                        (null)


Create        [UNKNOWN]CommandLine(STRING)            (null)

              [UNKNOWN]CurrentDirectory(STRING)

              [UNKNOWN]ProcessStartupInformation(OBJECT)

              [UNKNOWN]ProcessId(UINT32)

GetOwner      [UNKNOWN]Domain(STRING)                 (null)

              [UNKNOWN]User(STRING)

GetOwnerSid   [UNKNOWN]Sid(STRING)                    (null)

SetPriority   [IN ]Priority(SINT32)                   (null)

Terminate     [UNKNOWN]Reason(UINT32)                 (null)

Для получения более подробной помощи по этим методам нужно выполнить команду PROCESS CALL /?:FULL:

wmic:root\cli>PROCESS CALL /?:FULL
Вызов методов.
Использование:
CALL <имя метода> [<список фактических параметров>]
ЗАМЕЧАНИЕ. <список фактических параметров> ::= <факт. парам.> | 
  <факт. парам.>,  <список факти

Для псевдонима доступны следующие команды и методы:
Вызов    [ Ввод/Вывод ]Параметры и тип      Состояние
====     =====================                   ======
AttachDebugger                         (null)

Описание:
The AttachDebugger method launches the currently 
  registered debugger for this . . .

Create  [UNKNOWN]CommandLine(STRING)            (null)
              [UNKNOWN]CurrentDirectory(STRING)
              [UNKNOWN]ProcessStartupInformation(OBJECT)
              [UNKNOWN]ProcessId(UINT32)
Описание:
The Create method creates a new process. 
 It returns an integer value of 0 . . .
. . .

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

Пакетный режим работы, как отмечалось ранее, подразумевает запуск команд WMIC непосредственно из командной строки Windows или из пакетного файла. Для этого перед нужной командой пишется слово WMIC. При выполнении такой конструкции запускается WMIC, выполняется требуемая команда, после чего управление вновь передается командной строке Windows.

Например, для того чтобы вывести в пакетном режиме на экран свойства операционной системы, нужно в командной строке Windows выполнить команду WMIC OS.

Архитектура WMIC

Главными составными частями WMIC являются псевдонимы (aliases), средство синтаксического анализа и разбора вводимых команд (parser) и средства трансформации выходной информации в нужный формат.

Псевдонимы (aliases) в WMIC — это определения классов WMI, которые упрощают обращение к этим классам и их свойствам. Например, классу Win32_Process соответствует псевдоним PROCESS, а классу Win32_OperatingSystem — псевдоним OS. Таким образом, можно сказать, что псевдонимы выступают в качестве дружественных посредников между объектной моделью WMI и администратором операционной системы.

Стандартные псевдонимы определены для большинства часто используемых классов WMI, в случае необходимости можно создавать собственные псевдонимы или изменять существующие. Хранятся псевдонимы в виде экземпляров класса MSFT_CliAlias из пространства имен Root\Cli.

Пространство имен Root\Cli называется ролью (role) , в нем находятся и другие классы, связанные с WMIC ( MSFT_CliVerb, MSFT_CliFormat, MSFT_CliParam, MSFT_CliProperty, MSFT_CliConnection, MSFT_CliTranslateTable и т. д.). Вообще говоря, WMIC позволяет определить несколько ролей и производить переключение между ними, т. е. в CIM может быть помещено несколько независимых пространств имен, содержащих описания псевдонимов WMIC.

Над псевдонимами можно производить различные операции, которые определяются операторами, вводимыми в командной строке WMIC после имени псевдонима. Обработчик (парсер) для синтаксического разбора, интерпретации и выполнения операций с псевдонимами представлен исполняемым файлом wmic.exe, который находится в каталоге %SystemRoot%\System32\Wbem.

На рис. 14.1 представлена общая схема работы WMIC.

Схема работы WMIC


Рис. 14.1.  Схема работы WMIC

Итак, WMIC функционирует следующим образом. Обработчик wmic.exe получает введенную команду через стандартный входной поток Stdin. Парсер выполняет синтаксический разбор команды, выделяет псевдоним (если таковой имеется) и извлекает определение этого псевдонима для активной роли (напомним, что роли по умолчанию соответствует пространство имен Root\Cli). Кроме псевдонима в командной строке WMIC могут стоять операторы, задающие действие, которое нужно выполнить над псевдонимом. Обработка команды WMIC сводится, в конечном итоге, к выполнению последовательности вызовов соответствующих API-функций WMI в пространстве имен на локальном или удаленном компьютере.

Данные, которые возвращаются WMI в результате выполнения этих API-функций, автоматически преобразуются в формат XML. После этого данные форматируются тем или иным способом в соответствии с таблицей стилей XSL (eXtensible Stylesheet Language), которая связана с псевдонимом по умолчанию или явно задана с помощью соответствующих параметров оператора. Отформатированная информация возвращается пользователю через стандартный выходной поток Stdout.

Структура командной строки WMIC

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

Синтаксис командного языка WMIC

Команды, выполняемые в интерактивном режиме работы WMIC, должны иметь определенную структуру. В командной строке могут присутствовать глобальные параметры, псевдонимы, операторы (verbs) и команды, причем все эти компоненты должны записываться в строго заданном порядке.

Вообще говоря, синтаксис командного языка WMIC может быть представлен в нормальной форме Бэкуса-Наура (Backus-Naur Form, BNF), которая была разработана для описания языка Алгол-60 и затем использовалась для многих других языков программирования. При записи грамматики в форме Бэкуса-Наура используются несколько типов объектов.

Мы не будем здесь давать подробных правил построения и анализа формы Бэкуса-Наура, а лишь приведем для иллюстрации простой пример описания правила записи целого числа в этой форме:

<целое> ::= <целое без знака> | +<целое без знака> | -<целое без знака>
<целое без знака> ::= <цифра> | <целое без знака> <цифра>
<цифра> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

На практике чаще всего командная строка WMIC строится следующим образом:

[<глобальные параметры>] <псевдоним> 
  [WHERE <оператор WHERE>] [<оператор действия>]

Приведем несколько простых примеров.

Запустим WMIC и введем следующую команду:

SERVICE LIST

Здесь SERVICE является псевдонимом, а LIST — оператором действия, применяемым к этому псевдониму. В результате мы получим список всех служб, зарегистрированных на локальной машине:

wmic:root\cli>SERVICE LIST
AcceptPause  AcceptStop  Caption
ystemName  TagId  WaitHint
FALSE        FALSE       Оповещатель
FALSE        TRUE        Служба шлюза уровня приложения
FALSE        FALSE       Управление приложениями
FALSE        FALSE       ASP.NET State Service
. . .

Для того чтобы вывести сведения о конкретной службе (например, о службе оповещения), нужно использовать ключевое слово WHERE, например:

wmic:root\cli>SERVICE WHERE Name="Alerter" LIST
AcceptPause  AcceptStop  Caption  CheckPoint  CreationClassName . . .
FALSE  FALSE  Оповещатель  0  Win32_Service      Посылает . . .

Если необходимо получить информацию о службе оповещения на удаленном компьютере \\Server1, применяется глобальный параметр /NODE:

/NODE:"Server1" SERVICE WHERE Name="Alerter" LIST

Рассмотрим теперь более подробно каждый из компонентов командной строки WMIC.

Команды WMIC

WMIC поддерживает пять стандартных команд: CONTEXT, CLASS, PATH, QUIT и EXIT.

Команда CONTEXT

Команда CONTEXT позволяет увидеть значения всех глобальных параметров, которые используются в среде WMIC по умолчанию. Сами глобальные параметры и их возможные значения будут подробно рассмотрены далее.

Команда CLASS

С помощью команды CLASS можно получить доступ классу WMI напрямую, без использования псевдонима WMIC. Для этого в командной строке WMIC сразу после команды CLASS должен быть указан точный путь к этому классу WMI.

Таким образом, команда CLASS позволяет извлечь определение какого-либо класса WMI или создать его новые экземпляры. Например, для того чтобы увидеть все свойства и методы класса Win32_Process, можно выполнить следующую команду (результат будет выведен на экран в формате HTML):

CLASS Win32_Process
Команда PATH

Команда PATH применяется для прямого доступа к одному или нескольким экземплярам классов WMI, без указания псевдонимов WMIC. Команда PATH особенно полезна, если для нужного класса WMI не существует псевдонима WMIC.

Например, рассмотрим команду, в которой используется псевдоним PROCESS для вывода на экран некоторых сведений о запущенном Проводнике Windows:

PROCESS WHERE (Name="explorer.exe") GET Caption, 
  CommandLine, Handle

Так как псевдоним PROCESS соответствует классу Win32_Process, то эта команда равносильна следующей:

PATH Win32_Process WHERE (Name="explorer.exe") 
  GET Caption, CommandLine, Handle

Отметим также, что отбор конкретных экземпляров класса при использовании команды PATH, может производиться не только с помощью ключевого слова WHERE, но и путем задания полного пути к объекту через значения его ключевых свойств. Например, следующая команда равносильна двум предыдущим:

PATH Win32_Process.Name="explorer.exe" GET Caption, 
  CommandLine, Handle
Команды QUIT и EXIT

Команды QUIT и EXIT позволяют выйти из WMIC и вернуться в предыдущую оболочку (например, к командному приглашению Windows XP).

Глобальные параметры (ключи), настройки WMIC

В среде WMIC определены несколько глобальных параметров (ключей), которые по умолчанию применяются для всех вводимых в командной строке WMIC выражений. Как уже отмечалось ранее, для просмотра глобальных параметров используется команда CONTEXT. Для изменения значений этих параметров используется следующий синтаксис:

/Параметр:Значение

Далее описаны некоторые глобальные параметры WMIC.

Параметр /NODE

В параметр /NODE записываются разделяемые запятыми имена компьютеров, к которым будет обращаться WMIC при поиске классов WMI, соответсвующих вводимым в командной строке псевдонимам. Например:

/NODE:SERVER1,SERVER2

По умолчанию значением параметра /NODE является имя локального компьютера.

Имена компьютеров для параметра /NODE можно также брать из предварительно подготовленного текстового файла. В этом файле имена машин должны быть разделены либо запятыми, либо символами возврата каретки. Например, пусть на диске C имеется текстовый файл nodes.txt следующего содержания:

Server1,Server2
Server3

Тогда после выполнения команды

/NODE:@c:\nodes.txt

значением параметра /NODE станет список из трех имен компьютеров.

Параметр /PRIVILEGES

Напомним, что для выполнения средствами WMI операций, для которых необходимы специальные привилегии в операционных системах Windows NT/2000/XP (например, перезагрузка компьютера), необходимо установить режим использования всех привилегий при работе с WMI. Глобальный параметр /PRIVILEGES отвечает за этот режим при использовании WMIC.

По умолчанию в целях безопасности запрещено использовать все привилегии, значением параметра /PRIVILEGES при этом является DISABLE. Для того чтобы разрешить использовать все привилегии, нужно параметру /PRIVILEGES присвоить значение ENABLE:

/PRIVILEGES:ENABLE
Параметр /RECORD

С помощью параметра /RECORD можно сохранять во внешнем XML-файле историю запускаемых в текущей сессии WMIC команд и результаты их выполнения. Для включения режима записи команд нужно указать в качестве значения параметра /RECORD имя выходного XML-файла, например:

/RECORD:C:\outwmic.xml

Выполним теперь пару команд WMIC (например, CONTEXT и CPU LIST BRIEF ) и посмотрим в браузере Internet Explorer на содержимое выходного файла outwmic.xml (рис. 14.2).

Содержимое выходного XML-файла при включенном режиме записи команд


увеличить изображение

Рис. 14.2.  Содержимое выходного XML-файла при включенном режиме записи команд

Как мы видим, каждой выполненной команде соответствует элемент <RECORD>, который имеет несколько атрибутов (табл. 14.1).

Таблица 14.1. Атрибуты элемента <RECORD>
Атрибут Описание
SEQUENCENUMПорядковый номер выполняемой команды в сеансе WMIC
ISSUEDFROMИмя компьютера, на котором запускалась команда
STARTTIMEДата и время запуска команды

Внутри каждого из элементов <RECORD> находятся элементы <REQUEST> и <OUTPUT>, в которых хранятся соответственно данные о самой команде и о результате ее выполнения (рис. 14.3).

Данные о запущенной команде и результате ее выполнения


увеличить изображение

Рис. 14.3.  Данные о запущенной команде и результате ее выполнения

Внутри тегов <COMMANDLINE> и </COMMANDLINE> записан текст команды (в нашем случае это CONTEXT и CPU LIST BRIEF ).

У элемента <OUTPUT> имеются атрибуты TARGETNODE, значением которого является имя компьютера, на котором осуществлялся вывод информации, полученной в результате выполнения команды, и ITERATION, куда записывается номер итерации команды. Сами выходные данные команды помещаются внутрь секции <![CDATA[, которая, в свою очередь, находится внутри элемента <OUTPUT>.

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

Параметры /OUTPUT и /APPEND

Как уже отмечалось при описании архитектуры WMIC, по умолчанию все команды выводят информацию в стандартный выходной поток StdOut, т. е. на экран. Параметр /OUTPUT позволяет перенаправить вывод команд во внешний текстовый файл ( /OUTPUT:имя_файла ) или в буфер Windows ( /OUTPUT:CLIPBOARD ).

Отметим, что в отличие от параметра /RECORD, при перенаправлении вывода во внешний файл с помощью /OUTPUT в этот файл будет добавляться только результат выполнения команд, сами же команды записываться не будут. После перенаправления вывода в текстовый файл или буфер Windows на экран выходные данные команд выводиться не будут.

Часто бывает удобнее дублировать вывод на экран и в текстовый файл или буфер Windows. Для этого используется параметр /APPEND, в качестве значения которого указывается имя внешнего текстового файла (например, /APPEND:C:\OUT.TXT ), в который будет дублироваться выводимая командами информация (значением параметра /OUTPUT при этом должно быть STDOUT ).

Параметры /USER и /PASSWORD

Параметры /USER и /PASSWORD позволяют задать соответственно имя пользователя и пароль, которые будут использоваться во время доступа к компьютерам, имена которых заданы переключателем /NODE или указаны в псевдонимах. Имя пользователя здесь указывается в формате Домен\Пользователь. Например, для того чтобы получить доступ к подсистеме WMI на компьютере \\Server1 от имени пользователя Popov, зарегистрированного в домене Domain1, следует в командной строке WMIC ввести следующие переключатели:

/NODE:Server1 /USER:Popov /PASSWORD:"ser+-1"

Здесь мы явно указываем пароль, который содержит специальные символы ( "+" и "–" ), поэтому этот пароль заключен в двойные кавычки. Если не указывать параметр /PASSWORD, а только задать значение параметра /USER, то пароль будет запрошен с клавиатуры, причем вводится он с помощью неотображаемых символов.

Псевдонимы WMIC

Как уже говорилось ранее, псевдонимы используются в качестве посредников для получения доступа к инфраструктуре WMI из командной строки WMIC. Псевдонимы могут применяться для переименования классов WMI, а также свойств и методов этих классов, что позволяет обращаться к различным объектам WMI с помощью коротких и легко запоминающихся имен.

Псевдонимы имеются для большинства часто используемых классов WMI. Для того чтобы просмотреть список имеющихся псевдонимов, нужно вызвать в командной строке WMIC встроенную справку путем ввода команды /?. Для вывода информации о конкретном псевдониме, нужно вызвать встроенную справку по этому псевдониму. Например: PROCESS /?

В табл. 14.2 приведено краткое описание некоторых стандартных объектов WMIC и показано, какой WQL-запрос выполняется для создании того или иного псевдонима.

Таблица 14.2. Стандартные псевдонимы WMIC
ПсевдонимОписаниеWQL-запрос для построения псевдонима
ALIASДоступ к псевдонимам, зарегистрированным на локальном компьютереSELECT * FROM Msft_CliAlias
BIOSУправление базовой системой ввода-вывода (BIOS)SELECT * FROM Win32_BIOS
CPUУправление ЦПSELECT * FROM WIN32_PROCESSOR
DESKTOPУправление рабочим столомSELECT * FROM WIN32_DESKTOP
DISKDRIVEУправление физическими дискамиSELECT * FROM Win32_DiskDrive
ENVIRONMENTУправление настройками системной средыSELECT * FROM Win32_Environment
LOGICALDISKУправление локальными накопителямиSELECT * FROM Win32_LogicalDisk
OSУправление установленными операционными системамиSELECT * FROM Win32_OperatingSystem
PROCESSУправление процессамSELECT * FROM Win32_Process
SERVICEУправление служебными приложениямиSELECT * FROM Win32_Service
STARTUPУправление командами, запускающимися автоматически при входе пользователей в системуSELECT * FROM Win32_StartupCommand

Если в командной строке WMIC ввести имя псевдонима и нажать клавишу <Enter>, то будет выполнен WQL-запрос из табл. 14.2, который используется при создании этого псевдонима, т. е. будут выведены свойства всех экземпляров некоторого класса. Если же нам нужны сведения лишь о некоторых экземплярах этого класса, то следует применять условие WHERE, которое ставится сразу после имени псевдонима и должно содержать допустимое WQL-выражение. Например:

PROCESS WHERE (Name="notepad.exe")

Здесь будет выведена информация о процессах с именем notepad.exe (Блокнот Windows).

После имени псевдонима и условия WHERE может указываться оператор WMIC (например, GET, LIST или SET ), который задает действие, выполняемое над псевдонимом (описание операторов WMIC и соответствующие примеры их использования приведены далее).

Кроме этого, в псевдонимах определяются выходные форматы, которые могут включать значения свойств или предоставлять необходимые шаблоны для оформления данных. Например, в формате BRIEF перечисляются только значения свойств, существенных для идентификации объекта, доступ к которому осуществляется через этот псевдоним. Имена таких форматов вывода указываются в командной строке WMIC после оператора LIST, с помощью которого выводятся значения свойств псевдонима, указанных в данном формате. Например: PROCESS LIST BRIEF. Имена форматов вывода называются модификаторами оператора LIST.

Операторы (действия) WMIC

В этом разделе будут описаны некоторые стандартные операторы (действия) CALL, CREATE, SET, DELETE, GET и LIST, которые поддерживаются большинством псевдонимов WMIC. Псевдонимы могут также поддерживать другие действия. Чтобы получить сведения об операторах, доступных для некоторого псевдонима, нужно вывести встроенную справку для этого псевдонима, т. е. выполнить команду вида <псевдоним> /?.

Оператор CALL

С помощью оператора CALL можно выполнить метод класса или экземпляра класса WMI (путь к этому классу или экземпляру может быть задан либо с помощью псевдонима WMIC, либо с помощью команд CLASS и PATH ).

Для того чтобы узнать, какие методы доступны в псевдониме, а также какие параметры должны указываться при вызове определенного метода, нужно воспользоваться встроенной справкой WMIC.

Рассмотрим этот процесс более подробно. Предположим, что нам нужно запустить из среды WMIC стандартный калькулятор Windows (calc.exe). Так как для этого необходимо создать новый процесс, то сначала мы посмотрим, какие методы можно вызвать с помощью псевдонима PROCESS (или с помощью класса Win32_Process ). Для этого в командной строке WMIC введем одно из следующих выражений:

PROCESS CALL /?
CLASS Win32_Process CALL /?

В результате на экран выведется список доступных методов с описанием входных (IN) и выходных (OUT) параметров для каждого метода:

wmic:root\cli>PROCESS CALL /?
Вызов методов.
Использование:
CALL <имя метода> [<список фактических параметров>]
ЗАМЕЧАНИЕ. <список фактических параметров> ::= <факт. парам.> | 
  <факт. парам.>,. . .
Для псевдонима доступны следующие команды и методы:
Вызов     [ Ввод/Вывод ]Параметры и тип             Состояние
====      =====================                   ======
AttachDebugger                                   (null)
Create    [UNKNOWN]CommandLine(STRING)            (null)
          [UNKNOWN]CurrentDirectory(STRING)
          [UNKNOWN]ProcessStartupInformation(OBJECT)
          [UNKNOWN]ProcessId(UINT32)
GetOwner  [UNKNOWN]Domain(STRING)                 (null)
          [UNKNOWN]User(STRING)
GetOwnerSid [UNKNOWN]Sid(STRING)                    (null)
SetPriority [IN ]Priority(SINT32)                   (null)
Terminate [UNKNOWN]Reason(UINT32)                 (null)

Напомним, что для запуска метода необходимо, чтобы этот метод был реализован в провайдере соответствующего класса WMI. Индикатором такой реализации служит состояние метода Implemented.

При необходимости для каждого метода можно вывести его краткое описание. Для этого нужно использовать полный формат помощи: PROCESS CALL /?:FULL

Итак, мы видим, что новый процесс создается с помощью метода Create. Обязательным параметром CommandLine при этом является командная строка, содержащая путь к запускаемому исполняемому файлу (если в методе необходимо указывать несколько параметров, то эти параметры разделяются запятыми.). В нашем случае необходимо выполнить следующую команду:

PROCESS CALL Create calc.exe

В результате запустится калькулятор Windows и на экран выведутся выходные параметры метода Create (идентификатор ProcessID нового процесса и код возврата ReturnValue, нулевое значение которого говорит об успешном выполнении метода).

Для того чтобы закрыть запущенный калькулятор, нужно вызвать метод Terminate:

PROCESS WHERE Name="calc.exe" CALL Terminate
Оператор CREATE

Оператор CREATE позволяет создать новый экземпляр класса WMI и задать значения свойств этого экземпляра (новый класс с помощью CREATE создать нельзя). Класс WMI, экземпляр которого должен быть создан, задается с помощью псевдонима WMIC или команды CLASS ; после оператора CREATE указываются пары свойство–значение, которые разделяются запятыми (в качестве разделителя свойства и значения в паре используется знак равенства).

В качестве примера рассмотрим, каким образом оператор CREATE используется для создания новых переменных среды. Всем переменным среды, определенным в системе, соответствуют экземпляры класса Win32_Environment. В свою очередь, этому классу соответствует псевдоним ENVIRONMENT.

Для того чтобы узнать, какие свойства должны быть определены при создании нового экземпляра с помощью псевдонима ENVIRONMENT, нужно вызвать встроенную справку по оператору CREATE для данного псевдонима (команда ENVIRONMENT CREATE /?). В нашем случае нам потребуется задать имя переменной (параметр Name), ее значение (параметр VariableValue ) и имя пользователя (параметр UserName ), которому будет доступна эта переменная. Например, для создания переменной War1 со значением War1905 для пользователя Popov из домена Domain1, нужно выполнить следующую команду:

ENVIRONMENT CREATE Name="War1", VARIABLEVALUE="War1905",  
  UserName="Domain1\Popov"

Если же необходимо создать системную переменную, которая будет доступна всем пользователям, то необходимо в качестве значения параметра UserName указывать <SYSTEM>, например:

ENVIRONMENT CREATE Name="War2", VARIABLEVALUE="War1905",  
  UserName="<SYSTEM>"
Оператор SET

С помощью оператора SET можно изменить значения свойств у одного или нескольких экземпляров класса WMI, которые могут быть заданы с помощью псевдонима WMIC или команды CLASS. Напомним, что изменять значения можно далеко не у всех свойств. Чтобы узнать, какие свойства доступны для изменения у определенного псевдонима, нужно для этого псевдонима вывести встроенную справку по оператору SET. Например, выполнив команду ENVIRONMENT SET /?, можно увидеть, что у псевдонима ENVIRONMENT для изменения доступны только свойства Name и VariableValue.

Для того чтобы с помощью оператора SET изменить значения свойств, нужно, как и в операторе CREATE, указать разделенные запятыми пары вида Cвойство="Значение". Например, чтобы изменить имя системной переменной War2 на War3, а ее значение на War, следует выполнить следующую команду:

ENVIRONMENT WHERE Name="War2" SET Name="War3", VariableValue="War"
Оператор DELETE

Оператор DELETE производит удаление текущего экземпляра класса WMI или целого набора таких экземпляров (также DELETE может использоваться для удаления класса WMI). Например, для удаления созданной нами переменной среды War1 нужно выполнить следующую команду:

ENVIRONMENT WHERE Name="War1" DELETE

Если при этом с помощью глобального параметра /INTERACTIVE был включен интерактивный режим выполнения команд ( /INTERACTIVE:ON ), то перед удалением переменной будет задан дополнительный вопрос. Кроме этого, вне зависимости от значения глобального параметра /INTERACTIVE, дополнительный вопрос об удалении может быть выведен с помощью параметра /INTERACTIVE самого оператора DELETE:

ENVIRONMENT WHERE Name="War2" DELETE /INTERACTIVE

Параметр /NOINTERACTIVE, напротив, позволяет выполнить удаление без дополнительного подтверждения:

ENVIRONMENT WHERE Name="War2" DELETE /NOINTERACTIVE
Оператор GET

Оператор GET позволяет получить значения определенных свойств экземпляров классов WMI, которые могут задаваться с помощью псевдонимов WMIC или команды PATH.

Если же, используя команду CLASS, применить оператор GET к классу WMI, то мы получим описание этого класса. Например, после выполнения команды /OUTPUT:C:\1.htm CLASS Win32_Process GET в файле 1.htm сформируется описание класса Win32_Process.

Для того чтобы вывести на экран несколько свойств экземпляров класса, нужно указать имена этих свойств, разделенные запятыми, после оператора GET. Например: PROCESS GET Name, Handle.

Если ввести оператор GET без указания списка свойств, то будут выведены все свойства псевдонима.

Как уже отмечалось выше, одной из особенностей архитектуры WMIC является то, что XML-формат выходных данных может быть довольно легко изменен с помощью соответствующих таблиц стилей XSL. В операторе GET для этой цели служит параметр /FORMAT, в качестве значения которого указывается либо стандартное или определенное пользователем ключевое слово, задающее формат выходной информации, либо имя XSL-файла, с помощью которого будет происходить обработка выходных XML-данных. Стандартным ключевым словам (значениям параметра /FORMAT ) соответствуют XSL-файлы, которые расположены в каталоге %SystemRoot%\System32\Wbem; данное соответствие устанавливается в файле xsl-mapping.xml, который находится в том же каталоге (листинг 14.1).

<XSLMAPPINGS>
<XSLFORMAT KEYWORD="TABLE">WmiCliTableFormat.xsl</XSLFORMAT>
<XSLFORMAT KEYWORD="VALUE">WmiCliValueFormat.xsl</XSLFORMAT>
<XSLFORMAT KEYWORD="MOF">WmiCliMofFormat.xsl</XSLFORMAT>
<XSLFORMAT KEYWORD="LIST">WmiCliValueFormat.xsl</XSLFORMAT>
<XSLFORMAT KEYWORD="TVLIST">TextValueList.xsl</XSLFORMAT>
</XSLMAPPINGS>
Листинг 14.1. Стандартный файл xsl-mapping.xml (html, txt)

В файл xsl-mapping.xml можно добавлять собственные ключевые слова, связывая их со своими XSL-файлами. Стандартные форматы вывода оператора GET описаны в табл. 14.3.

Таблица 14.3. Стандартные форматы вывода оператора GET
Значение параметра /FORMAT Описание
CSVЗначения свойств экземпляра класса выводятся в одну строку и отделяются друг от друга запятыми
HFORMИнформация выводится в виде совокупности HTML-таблиц для каждого из экземпляров класса. В первом столбце этих таблиц записывается имя свойства, а во втором — значение этого свойства
HTABLEИнформация выводится в виде одной HTML-таблицы, в которой каждая строка соответствует одному экземпляру класса. В заголовках столбцов этой таблицы записываются названия выводимых свойств, а в самих столбцах — значения этих свойств
LISTФормат вывода аналогичен случаю GET /VALUE — каждое свойство и его значение выводятся в отдельной строке
MOFВыходные данные преобразуются в MOF-формат
RAWXMLФормируются XML-элементы, содержащие подробную информацию о выполняемой команде и результатах ее обработки
TABLEФормат вывода аналогичен случаю GET /ALL — данные выводятся в табличном виде
VALUEТо же самое, что LIST
XMLВыходные данные с дополнительной информацией о выполняемой команде преобразуются в XML-формат
Оператор LIST

Оператор LIST, как и GET, позволяет вывести значения свойств экземпляров классов WMI, которые могут задаваться с помощью псевдонимов WMIC или команды PATH. Этот оператор выполняется для псевдонимов по умолчанию, т. е. если в командной строке WMIC вводится один псевдоним без оператора, то к этому псевдониму применяется оператор LIST.

В отличие от оператора GET, с помощью LIST нельзя вывести данные для произвольных свойств экземпляров класса WMI. В операторе LIST можно лишь выбрать один из имеющихся наборов свойств, которые задаются модификаторами. Общий синтаксис оператора LIST таков:

LIST [<модификатор>] [<параметры>]

Отметим, что наборы модификаторов для различных псевдонимов могут отличаться друг от друга. Однако есть несколько стандартных модификаторов, которые имеются почти у всех псевдонимов (табл. 14.4).

Таблица 14.4. Стандартные модификаторы оператора LIST
Модификатор Описание
BRIEFВыводятся основные свойства псевдонима
FULLВыводятся все свойства псевдонима (используется по умолчанию)
INSTANCEНа экран будут выводиться только пути экземпляров класса (значение свойства __PATH )
STATUSОтображается состояние объектов
SYSTEMВыводятся системные свойства псевдонима

Для того чтобы узнать, какие именно модификаторы доступны для определенного псевдонима, и какие свойства входят в эти модификаторы, нужно воспользоваться встроенной справкой для оператора LIST, например: PROCESS LIST /?

После модификатора в операторе LIST могут указываться параметры /FORMAT и /TRANSLATE, которые имеют тот же смысл, что и в рассмотренном ранее операторе GET.

Лекция 15. Форматы вывода данных WMIC. Типичные команды для администрирования

Обсуждаются форматы вывода для команд WMIC. Даются примеры команд WMIC, которые могут оказаться полезными для администратора операционной системы

Форматы вывода данных WMIC. Типичные команды для администрирования

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

Стандартные форматы вывода

По умолчанию WMIC поддерживает несколько форматов вывода.

Вывод в буфер Windows

Иногда бывает удобно перенаправить вывод команд WMIC в буфер Windows, например, для последующей вставки результатов выполнения команды в документ Microsoft Word. Для этого нужно в командной строке WMIC глобальному параметру /OUTPUT присвоить значение CLIPBOARD:

/OUTPUT:CLIPBOARD

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

Вывод в XML-файл

Сохранять в XML-файле информацию о запускаемых командах WMIC и выводимых ими результатах можно двумя способами: с помощью глобального параметра /RECORD или с помощью формата вывода RAWXML.

Если в XML-файле не нужно будет производить детальный разбор выводимых командами данных, то проще задать выходной файл с помощью параметра /RECORD, например:

/RECORD:C:\out_wmic.xml

После этого каждой вводимой команде WMIC в этом файле будет соответствовать элемент <RECORD>, внутри которого будут записаны элементы <REQUEST> с информацией о команде и <OUTPUT> с результатом выполнения команды в блоке <![CDATA[.

Для того чтобы отменить такой вывод в XML-файл, нужно либо закрыть сеанс WMIC, либо присвоить параметру /RECORD пустое значение: /RECORD:""

Если же требуется полностью структурировать выводимую командами LIST или GET информацию, то можно воспользоваться форматом вывода RAWXML и перенаправить вывод во внешний файл с помощью параметра /OUTPUT, например:

/OUTPUT:C:\out_xml.xml CPU LIST BRIEF /FORMAT:RAWXML

Корневым элементом в файле out_xml.xml будет элемент <COMMAND>, в атрибутах которого записан порядковый номер выполняемой команды в сеансе WMIC ( SEQUENCENUM ), имя компьютера, на котором была запущена команда ( ISSUEDFROM ), время начала выполнения команды ( STARTTIME ) и количество повторов команды ( EVERYCOUNT ).

Элемент <REQUEST> является контейнером, внутри которого находятся элементы, содержащие информацию о запущенной команде и значениях параметров WMIC, которые были установлены во время запуска команды.

Элемент <COMMANDLINE> содержит полный текст запускаемой программы:

<COMMANDLINE> /OUTPUT:C:\out_xml.xml CPU LIST BRIEF /
  FORMAT:RAWXML </COMMANDLINE>

В контейнере <COMMANDLINECOMPONENTS> находятся элементы, полученные в результате разбора командной строки. Элемент <NODELIST> содержит список компьютеров (элементы <NODE> ), на которых запускалась команда.

В элементе <FRIENDLYNAME> хранится имя используемого псевдонима WMIC, в <TARGET> — текст WQL-запроса, который соответствует псевдониму, в <ALIASTARGET> — название класса WMI, к которому происходит обращение:

<FRIENDLYNAME>CPU</FRIENDLYNAME> 
<TARGET>Select * from WIN32_PROCESSOR</TARGET> 
<ALIASTARGET>WIN32_PROCESSOR</ALIASTARGET>

Элемент <NAMESPACE> содержит путь к используемому пространству имен CIM, в элементе <RESULTANTQUERY> записан текст WQL-запроса, который был выполнен при запуске команды (в нашем примере этот запрос построен с учетом модификатора BRIEF ):

<NAMESPACE>ROOT\CIMV2</NAMESPACE> 
<RESULTANTQUERY> SELECT Caption, DeviceID, Manufacturer, 
  MaxClockSpeed, Name, SocketDesignation FROM WIN32_PROCESSOR 
    </RESULTANTQUERY>

В элементе <FORMATS> приведен список XSL-файлов, которые используются для форматирования результатов выполнения команды.

В элементе <PROPERTIES> находятся описания всех свойств класса WMI, которые фигурируют в выполняемом запросе. Каждому такому свойству соответствует элемент <PROPERTY>.

Значения всех глобальных параметров WMIC, каждому из которых соответствует свой XML-элемент, собраны внутри контейнера <CONTEXT>.

Результаты выполнения запущенной команды находятся внутри элемента <CIM> в контейнере <RESULTS>.

Внутри контейнера <CIM> находятся элементы <INSTANCE>, соответствующие экземплярам класса WMI, выбранным в результате выполнения WQL-запроса. Каждый элемент <INSTANCE> содержит элементы <PROPERTY>, соответствующие свойствам экземпляра класса WMI (имя свойства записано в атрибуте NAME, тип свойства — в атрибуте TYPE ). Внутри элемента <PROPERTY> находится элемент <VALUE>, значение которого совпадает со значением соответствующего свойства экземпляра класса WMI.

Вывод в HTML-файл

С помощью стандартных форматов вывода HFORM и HTABLE можно, используя параметр /OUTPUT, сформировать HTML-файлы двух видов с результатами выполнения операторов LIST и GET.

Формат вывода HFORM позволяет представить выходную информацию в виде совокупности HTML-таблиц для каждого из экземпляров класса, выбранного в результате выполнения команды. При этом в первом столбце этих таблиц записывается имя свойства, а во втором — значение этого свойства. Например, выполним команду

/OUTPUT:C:\hf.htm PROCESS LIST BRIEF /FORMAT:HFORM

и откроем полученный файл hf.htm с помощью браузера Internet Explorer (рис. 15.1).

Пример выходного HTML-файла, полученного с помощью формата HFORM


Рис. 15.1.  Пример выходного HTML-файла, полученного с помощью формата HFORM

С помощью формата HTABLE можно поместить всю выводимую информацию в одну HTML-таблицу, в которой каждая строка соответствует одному экземпляру класса. В заголовках столбцов этой таблицы записываются названия выводимых свойств, а в самих столбцах — значения этих свойств. Например, на рис. 15.2 показан открытый в браузере Internet Explorer файл ht.htm, который был сформирован в результате выполнения следующей команды:

/OUTPUT:C:\ht.htm PROCESS LIST BRIEF /FORMAT:HTABLE

Пример выходного HTML-файла, полученного с помощью формата HTABLE


увеличить изображение

Рис. 15.2.  Пример выходного HTML-файла, полученного с помощью формата HTABLE

Кроме этого, таблица, получаемая с помощью формата HTABLE, может быть отсортирована по любому столбцу с помощью параметра sortby (название параметра обязательно должно быть набрано маленькими буквами), в качестве значения которого должно быть указано имя нужного столбца (свойства). Например, для получения таблицы процессов, отсортированной по полю Name, нужно выполнить следующую команду:

/OUTPUT:C:\ht.htm PROCESS LIST BRIEF /FORMAT:HTABLE:"sortby=Name"
Вывод в текстовый файл

Для того чтобы перенаправить вывод операторов LIST и GET в текстовый файл, используется параметр /OUTPUT вместе с форматами вывода TEXTTABLE, TEXTTABLEWSYS и TEXTVALUELIST.

Формат TEXTTABLE позволяет получить информацию в табличном виде, где каждая колонка соответствует определенному свойству класса WMI, причем числовые значения форматируются в соответствии с региональными настройками Windows.

Формат TEXTTABLEWSYS также позволяет получить таблицу аналогичной структуры, однако числовые значения здесь выводятся без дополнительного форматирования.

С помощью формата TEXTVALUELIST можно для каждого возвращаемого экземпляра класса WMI получить список пар вида свойство=значение.

Вывод в CSV-файл

Стандартный формат вывода CSV позволяет преобразовывать информацию, возвращаемую командами WMIC, в формат файла с разделителями, при этом в качестве разделителя выступает запятая. Данные файлы потом могут быть легко открыты, например, с помощью программы Microsoft Excel.

Для примера выполним следующую команду:

/OUTPUT:C:\klop.csv PROCESS LIST BRIEF /FORMAT:CSV

В результате на диске C формируется текстовый файл klop.csv, в первой строке которого будут записаны разделенные запятыми названия свойств псевдонима PROCESS, а в остальных строках — значения этих свойств для всех процессов, запущенных в системе:

Node,HandleCount,Name,Priority,ProcessId,ThreadCount,WorkingSetSize,
POPOV,0,System Idle Process,0,0,1,20480,
POPOV,194,System,8,4,50,131072,
POPOV,21,SMSS.EXE,11,364,3,159744,
...

Примеры команд WMIC

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

Завершение сеанса пользователя

Для того чтобы принудительно завершить сеанс пользователя, можно воспользоваться методом Win32ShutDown псевдонима OS. Этот метод имеет один обязательный параметр, задающий действие, которое нужно произвести при завершении работы пользователя (это может быть завершение сеанса, перезагрузка или выключение компьютера). Для завершения сеанса пользователя значение этого параметра должно быть равно нулю.

Отметим, что метод Win32ShutDown нельзя вызвать, не указав с помощью оператора WHERE конкретный экземпляр псевдонима OS, причем даже в том случае, когда у псевдонима OS имеется единственный экземпляр, поэтому обязательно нужно применить оператор WHERE, задав в качестве условия, скажем, совпадение значения свойства CSNAME с именем компьютера, на котором вызывается метод. Например:

/NODE:POPOV OS WHERE(CSNAME="POPOV") CALL Win32ShutDown 0
Перезагрузка и выключение компьютера

Для перезагрузки компьютера нужно вызвать метод Win32ShutDown с параметром 2. Например:

/NODE:POPOV OS WHERE(CSNAME="POPOV") CALL Win32ShutDown 2

Выключение компьютера производится путем запуска метода Win32ShutDown с параметром 1. Например:

/NODE:POPOV OS WHERE(CSNAME="POPOV") CALL Win32ShutDown 1

Замечание

Для выполнения метода Win32ShutDown у пользователя должен быть установлен режим использования всех привилегий ( /PRIVILEGES:ENABLE ).

Вывод информации о BIOS

Для получения информации о BIOS (версия, серийный номер, дата выпуска и т. д.) следует вывести свойства псевдонима BIOS:

/OUTPUT:C:\bios.txt BIOS GET /FORMAT:TEXTVALUELIST

В этом примере данные выводятся в текстовый файл bios.txt, содержимое которого представлено в листинге 15.1.

Замечание

Изменять значения свойств у псевдонима BIOS нельзя.

BiosCharacteristics={7,9,10,11,12,15,16,19,20,21,22,
  23,24,25,26,27,28,29,30,32,33,34,36,37,40,41}
BIOSVersion={"INTEL  - 20050804","BIOS Date: 08/04/05 
 00:31:45 Ver: 08.00.10","BIOS Date: 08/04/05 00:31:45 
   Ver: 08.00.10"}
BuildNumber=
Caption=BIOS Date: 08/04/05 00:31:45 Ver: 08.00.10
CodeSet=
CurrentLanguage=enUS
Description=BIOS Date: 08/04/05 00:31:45 Ver: 08.00.10
IdentificationCode=
InstallableLanguages=1
InstallDate=
LanguageEdition=
ListOfLanguages={"enUS"}
Manufacturer=Intel Corp.
Name=BIOS Date: 08/04/05 00:31:45 Ver: 08.00.10
OtherTargetOS=
PrimaryBIOS=TRUE
ReleaseDate=20050804000000.000000+000
SerialNumber= 
SMBIOSBIOSVersion=BF86510A.86A.0077.P25.0508040031
SMBIOSMajorVersion=2
SMBIOSMinorVersion=3
SMBIOSPresent=TRUE
SoftwareElementID=BIOS Date: 08/04/05 00:31:45 Ver: 08.00.10
SoftwareElementState=3
Status=OK
TargetOperatingSystem=0
Version=INTEL  - 20050804
Листинг 15.1. Информация о BIOS (html, txt)
Просмотр параметров загрузки

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

wmic:root\cli>BOOTCONFIG GET /VALUE

BootDirectory=\WINDOWS
Caption=\Device\Harddisk0\Partition1
ConfigurationPath=\WINDOWS
Description=\Device\Harddisk0\Partition1
LastDrive=D:
Name=BootConfiguration
ScratchDirectory=C:\WINDOWS\system32\config\
  systemprofile\Local Settings\Temp
SettingID=
TempDirectory=C:\WINDOWS\system32\config\
systemprofile\Local Settings\Temp

Изменять значения свойств у псевдонима BOOTCONFIG нельзя.

Вывод свойств операционной системы

С помощью псевдонима OS можно просмотреть различные свойства операционной системы, которые могут быть весьма полезны администратору (например, в свойстве LastBootUpTime содержится время последней загрузки системы). Следующая команда выводит все свойства псевдонима OS в текстовый файл os.txt (листинг 15.2):

/OUTPUT:C:\os.txt OS GET /VALUE

Замечание

Свойства CurrentTimeZone, Description, ForegroundApplicationBoost, QuantumLength и QuantumType у псевдонима OS доступны для записи.

BootDevice=\Device\HarddiskVolume1
BuildNumber=2600
BuildType=Uniprocessor Free
Caption=Microsoft Windows XP Professional
CodeSet=1251
CountryCode=7
CreationClassName=Win32_OperatingSystem
CSCreationClassName=Win32_ComputerSystem
CSDVersion=Service Pack 2
CSName=404-POPOV
CurrentTimeZone=240
DataExecutionPrevention_32BitApplications=FALSE
DataExecutionPrevention_Available=FALSE
DataExecutionPrevention_Drivers=FALSE
DataExecutionPrevention_SupportPolicy=2
Debug=FALSE
Description=Microsoft Windows XP Professional
Distributed=FALSE
EncryptionLevel=168
ForegroundApplicationBoost=2
FreePhysicalMemory=66448
FreeSpaceInPagingFiles=327124
FreeVirtualMemory=2056540
InstallDate=20060518120320.000000+240
LargeSystemCache=0
LastBootUpTime=20070919081646.682500+240
LocalDateTime=20070919160053.807000+240
Locale=0419
Manufacturer=Microsoft Corporation
MaxNumberOfProcesses=-1
MaxProcessMemorySize=2097024
Name=Microsoft Windows XP Professional|C:\WINDOWS|\Device\Harddisk0\Partition1
NumberOfLicensedUsers=
NumberOfProcesses=36
NumberOfUsers=2
Organization=SBRF
OSLanguage=1049
OSProductSuite=
OSType=18
OtherTypeDescription=
PlusProductID=
PlusVersionNumber=
Primary=TRUE
ProductType=1
QuantumLength=0
QuantumType=0
RegisteredUser=Evg
SerialNumber=55683-640-7090775-23275
ServicePackMajorVersion=2
ServicePackMinorVersion=0
SizeStoredInPagingFiles=639676
Status=OK
SuiteMask=272
SystemDevice=\Device\HarddiskVolume1
SystemDirectory=C:\WINDOWS\system32
SystemDrive=C:
TotalSwapSpaceSize=
TotalVirtualMemorySize=2097024
TotalVisibleMemorySize=259820
Version=5.1.2600
WindowsDirectory=C:\WINDOWS
Листинг 15.2. Информация об операционной системе (html, txt)
Получение информации о процессоре

Получить информацию об установленных процессорах можно с помощью псевдонима CPU. В свойстве DeviceID этого псевдонима хранится идентификатор процессора ( CPU0, CPU1 и т. д.), в свойстве Name — имя процессора, в CurrentClockSpeed — текущая частота и т. д. В листинге 15.3 представлено содержимое файла cpu.txt с информацией об одном процессоре. Файл cpu.txt сформирован с помощью следующей команды:

/OUTPUT:C:\cpu.txt CPU GET /VALUE

Замечание

Изменять значения свойств у псевдонима CPU нельзя.

AddressWidth=32
Architecture=0
Availability=3
Caption=x86 Family 6 Model 8 Stepping 10
ConfigManagerErrorCode=
ConfigManagerUserConfig=
CpuStatus=1
CreationClassName=Win32_Processor
CurrentClockSpeed=897
CurrentVoltage=22
DataWidth=32
Description=x86 Family 6 Model 8 Stepping 10
DeviceID=CPU0
ErrorCleared=
ErrorDescription=
ExtClock=100
Family=15
InstallDate=
L2CacheSize=128
L2CacheSpeed=897
LastErrorCode=
Level=6
LoadPercentage=0
Manufacturer=GenuineIntel
MaxClockSpeed=897
Name=Процессор Intel Celeron
OtherFamilyDescription=
PNPDeviceID=
PowerManagementSupported=FALSE
ProcessorId=0383F9FF0000068A
ProcessorType=3
Revision=2058
Role=CPU
SocketDesignation=Socket 370
Status=OK
StatusInfo=3
Stepping=10
SystemCreationClassName=Win32_ComputerSystem
SystemName=POPOV
UniqueId=
UpgradeMethod=1
Version=Модель 8, Выпуск 10
VoltageCaps=
Листинг 15.3. Информация о процессоре (html, txt)
Получение информации об оперативной памяти

Получить сведения об оперативной памяти можно с помощью трех псевдонимов WMIC: MEMPHYSICAL (информация о физической памяти), MEMCACHE (информация о кэш-памяти) и MEMLOGICAL (информация о логической памяти). Запустим команду MEMLOGICAL GET /VALUE:

wmic:root\cli>MEMLOGICAL GET /VALUE
AvailableVirtualMemory=293476
Caption=Конфигурация логической памяти
Description=Конфигурация логической памяти
Name=LogicalMemoryConfiguration
SettingID=LogicalMemoryConfiguration
TotalPageFileSpace=639676
TotalPhysicalMemory=259820
TotalVirtualMemory=899496

Как мы видим, псевдоним MEMLOGICAL позволяет, в частности, узнать общий объем физической памяти (свойство TotalPhysicalMemory ) и объем виртуальной памяти (свойство TotalVirtualMemory ).

Получение информации о свойствах и состоянии служб

Получить доступ к сведениям о зарегистрированных в системе службах можно с помощью псевдонима SERVICE. Например, для того чтобы сформировать HTML-таблицу, содержащую информацию о состоянии всех зарегистрированных служб на компьютерах \\Server1 и \\Server2, можно выполнить следующую команду:

/NODE:Server1,Server2 /OUTPUT:C:\service.htm 
  SERVICE GET Name, DisplayName, State /FORMAT:HTABLE

Замечание

Изменять значения свойств псевдонима SERVICE нельзя.

Запуск и остановка служб

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

Для запуска служб предназначен метод StartService. Например, для того чтобы запустить службы Microsoft SQL Server на сервере \\Server1, нужно выполнить следующую команду:

/NODE:Server1 SERVICE WHERE(Name="MSSQLSERVER") CALL StartService

Для остановки этой же службы используется метод StopService:

/NODE:Server1 SERVICE WHERE(Name="MSSQLSERVER") CALL StopService
Создание и завершение процессов

Для создания новых процессов используется метод Create псевдонима PROCESS, в качестве обязательного параметра которого указывается путь к запускаемому исполняемому файлу. Например, следующая команда откроет стандартный Блокнот Windows:

PROCESS CALL Create Notepad.exe

Отметим, что при таком использовании метода Create нужно следить за параметром ReturnValue, ненулевое значение которого служит индикатором ошибки, произошедшей во время выполнении метода. Если же ReturnValue равно нулю, то значит метод Create выполнился успешно. Завершить процесс можно с помощью метода Terminate:

PROCESS WHERE (Name="Notepad.exe") CALL Terminate

У метода Terminate также есть выходной параметр ReturnValue, который здесь имеет тот же смысл, что и в методе Create.

Лекция 16. Введение в оболочку командной строки Windows PowerShell

Описываются возможности оболочки Windows PowerShell и отличие ее от традиционных оболочек и языков сценариев. Обсуждаются основные концепции PowerShell (типы команд, структура командлетов, псевдонимы команд). Рассматриваются особенности справочной системы PowerShell

Введение в оболочку командной строки Windows PowerShell

На настоящий момент мы рассмотрели уже три разных инструмента, предназначенных для автоматизации работы в операционной системе Windows: оболочки командной строки Cmd.exe и WMIC, а также сервер сценариев WSH. Зачем же компании Microsoft понадобилась разработка еще одной полностью новой оболочки командной строки со своим языком сценариев?

Причины и цели создания новой оболочки

Чтобы ответить на этот вопрос, вспомним основные требования к "идеальному" средству автоматизации, которые мы обсуждали в первой лекции, и посмотрим, в какой степени удовлетворяют этим требованиям перечисленные выше инструменты (табл.16.1).

Таблица 16.1. Требования к инструменту автоматизации
Требование Cmd.exe WSH WMIC
Работа во всех версиях операционной системы без установки дополнительного программного обеспеченияДаДаНет (только Windows XP и выше)
Интеграция с командной строкойДаНетДа
Согласованный и непротиворечивый синтаксис команд и утилитНетНетДа
Поддержка псевдонимов (кратких синонимов) для длинных названий командНетНетДа
Автоматическое завершения команд и имен файлов при вводе их с клавиатурыЧастично (автоматическое завершение имен файлов и папок)НетНет
Поддержка истории введенных команд с возможностью их повторного вызова, просмотра и редактированияДаНетДа
Наличие подробной встроенной справки по командам с примерами использованияЧастичноНетДа
Возможность автоматического выполнения сценариевДа (язык командных файлов)Да (языки сценариев VBScript, JScript и т.д.)Частично (команды WMIC можно встраивать в командные файлы)
Доступ и использование всех технологий и возможностей, поддерживаемых операционной системойНет (нет прямого доступа к объектам COM, WMI, ADSI, .NET)ДаНет (доступ только к объектам WMI)

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

Новая оболочка Windows PowerShell (предварительно она была названа Monad) была задумана разработчиками Microsoft как более мощная среда для написания сценариев и работы из командной строки. Разработчики PowerShell преследовали несколько целей. Главная и самая амбициозная из них – создать среду составления сценариев, которая наилучшим образом подходила бы для современных версий операционной системы Windows и была бы более функциональной, расширяемой и простой в использовании, чем какой-либо аналогичный продукт для любой другой операционной системы. В первую очередь эта среда должна была подходить для решения задач, стоящих перед системными администраторами (тем самым Windows получила бы дополнительное преимущество в борьбе за сектор корпоративных платформ), а также удовлетворять требованиям разработчиков программного обеспечения, предоставляя им средства для быстрой реализации интерфейсов управления к создаваемым приложениям.

Для достижения этих целей были решены следующие задачи:

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

Отличие PowerShell от других оболочек – ориентация на объекты

При разработке любого языка программирования одним из основных является вопрос о том, какие типы данных и каким образом будут в нем представлены. При создании PowerShell разработчики решили не изобретать ничего нового и воспользоваться унифицированной объектной моделью .NET. Данный выбор был сделан по нескольким причинам.

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

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

В-третьих, работая в оболочке с объектами, можно с помощью их свойств и методов легко получать нужные данные, не занимаясь разбором и анализом символьной информации, как это происходит во всех традиционных тексто-ориентированных оболочках командной строки. Рассмотрим пример. В Windows XP есть консольная утилита tasklist.exe, которая выдает информацию о процессах запущенных в системе:

C:\>tasklist

Имя образа                   PID Имя сессии       № сеанса       Память
========================= ====== ================ ======== ============
System Idle Process            0                         0        16 КБ
System                         4                         0        32 КБ
smss.exe                     560                         0        68 КБ
csrss.exe                    628                         0     4 336 КБ
winlogon.exe                 652                         0     3 780 КБ
services.exe                 696                         0     1 380 КБ
lsass.exe                    708                         0     1 696 КБ
svchost.exe                  876                         0     1 164 КБ
svchost.exe                  944                         0     1 260 КБ
svchost.exe                 1040                         0    10 144 КБ
svchost.exe                 1076                         0       744 КБ
svchost.exe                 1204                         0       800 КБ
spoolsv.exe                 1296                         0     1 996 КБ
kavsvc.exe                  1516                         0     9 952 КБ
klnagent.exe                1660                         0     5 304 КБ
klswd.exe                   1684                         0        64 КБ

Предположим, что мы в командном файле интерпретатора Cmd.exe с помощью этой утилиты хотим определить, сколько оперативной памяти тратит процесс kavsvc.exe. Для этого нужно выделить из выходного потока команды tasklist соответствующую строку, извлечь из нее подстроку, содержащую нужное число и убрать пробелы между разрядами (при этом следует учесть, что в зависимости от настроек операционной системы разделителем разрядов может быть не пробел, а другой символ). В PowerShell аналогичная задача решается с помощью команды get-process, которая возвращает коллекцию объектов, каждый из которых соответствует одному запущенному процессу. Для определения памяти, затрачиваемой процессом kavsvc.exe, нет необходимости в дополнительных манипуляциях с текстом, достаточно просто взять значение свойства WS объекта, соответствующего данному процессу.

Наконец, объектная модель .NET позволяет PowerShell напрямую использовать функциональность различных библиотек, являющихся частью платформы .NET. Например, чтобы узнать, каким днем недели было 9 ноября 1974 года, в PowerShell можно выполнить следующую команду:

(get-date "09.11.1974").DayOfWeek

В этом случае команда get-date возвращает .NET-объект DateTime, имеющий свойство, при обращении к которому вычисляется день недели для соответствующей даты. Таким образом, разработчикам PowerShell не нужно создавать специальную библиотеку для работы с датами и временем – они просто берут готовое решение в .NET.

Загрузка и установка PowerShell

Оболочка PowerShell может работать не во всех версиях операционной системы, ее можно использовать в Windows XP SP 2, Windows Server 2003 SP 1 и более поздних версиях. Кроме этого, в системе должна быть установлена платформа .NET Framework 2.0 (в Windows XP данную среду придется устанавливать дополнительно, дистрибутив можно загрузить с сайта Microsoft по адресу http://msdn.microsoft.com/netframework/downloads/updates/default.aspx).

Загрузить PowerShell можно с сайта Microsoft, открыв страницу http://microsoft.com/powershell, где имеются ссылки на файл установки последней версии и пакеты документации на разных языках. Запустив загруженный файл, следуйте указаниям мастера установки. В 32-разрядных версиях Windows оболочка PowerShell устанавливается по умолчанию в каталог %SystemRoot%\System32\WindowsPowerShell\v1.0. В 64-разрядных версиях Windows 32-разрядная версия PowerShell устанавливается в каталог %SystemRoot%\SystemWow64\WindowsPowerShell\v1.0, а 64-разрядная версия Windows PowerShell устанавливается в каталог %SystemRoot%\System32\WindowsPowerShell\v1.0.

Запуск оболочки. Выполнение команд

Установив оболочку в системе, можно начать новый интерактивный сеанс. Для этого следует нажать на кнопку Пуск (Start), открыть меню Все программы (All Programs) и выбрать элемент Windows PowerShell. Другой вариант запуска оболочки – пункт Выполнить… (Run) в меню Пуск (Start), ввести имя файла powershell и нажать кнопку OK.

В результате откроется новое командное окно с приглашением вводить команды (рис. 16.1).

Командное окно оболочки PowerShell


увеличить изображение

Рис. 16.1.  Командное окно оболочки PowerShell

Выполним первую команду в PowerShell. Пусть это будет что-то знакомое, например dir (команды в PowerShell обрабатываются без учета регистра). На экран будет выведен список файлов в текущем каталоге:

PS C:\Documents and Settings\User> dir
    Каталог: Microsoft.PowerShell.Core\FileSystem::C:\Documents 
      and Settings\User
Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d---s        14.12.2007     10:10            Cookies
d----        12.05.2005     17:16            DoctorWeb
d----        06.11.2004     13:03            Phone Browser
d---s        22.09.2004     23:49            UserData
d-r--        04.10.2004     15:33            Главное меню
d-r--        05.12.2007      0:49            Избранное
d-r--        31.10.2007     21:03            Мои документы
d----        05.12.2007     10:54            Рабочий стол
-a---        24.05.2006     21:22       8304 gsview32.ini

Типы команд PowerShell

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

Первый тип – так называемые командлеты (cmdlet). Этот термин используется пока только внутри PowerShell. Командлет представляет собой класс .NET, порожденный от базового класса Cmdlet ; разрабатываются командлеты с помощью пакета PowerShell Software Developers Kit (SDK). Единый базовый класс Cmdlet гарантирует совместимый синтаксис всех командлетов, а также автоматизирует анализ параметров командной строки и описание синтаксиса командлетов для встроенной справки.

Данный тип команд компилируется в динамическую библиотеку (DLL) и подгружается к процессу PowerShell во время запуска оболочки (то есть сами по себе командлеты не могут быть запущены как приложения, но в них содержатся исполняемые объекты). Так как компилированный код подгружается к процессу оболочки, данный тип команд выполняется наиболее эффективно. Командлеты – это аналог внутренних команд традиционных оболочек.

Следующий тип команд – функции. Функция – это блок кода на языке PowerShell, имеющий название и находящийся в памяти до завершения текущего сеанса командной оболочки. Функции, как и командлеты, поддерживают именованные параметры. Анализ синтаксиса функции производится один раз при ее объявлении.

Сценарий – это блок кода на языке PowerShell, хранящийся во внешнем файле с расширением ps1. Анализ синтаксиса сценария производится при каждом его запуске.

Последний тип команд – внешние исполняемые файлы, которые выполняются обычным образом операционной системой.

Имена и структура командлетов

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

Имена командлетов всегда соответствуют шаблону "глагол-существительное", где глагол задает определенное действие, а существительное определяет объект, над которым это действие будет совершено.

Например, Get-Process (получить информацию о процессе), Stop-Service (остановить службу), Clear-Host (очистить экран консоли) и т.д. Чтобы просмотреть список командлетов, доступных в ходе текущего сеанса, нужно выполнить командлет Get-Command:

PS C:\> Get-Command

CommandType  Name            Definition
-----------  ----            ----------
Cmdlet       Add-Content     Add-Content [-Path] <String[]> [-Value] <Object[...
Cmdlet       Add-History     Add-History [[-InputObject] <PSObject[]>] [-Pass...
Cmdlet       Add-Member      Add-Member [-MemberType] <PSMemberTypes> [-Name]...
Cmdlet       Add-PSSnapin    Add-PSSnapin [-Name] <String[]> [-PassThru] [-Ve...
Cmdlet       Clear-Content   Clear-Content [-Path] <String[]> [-Filter <Strin...
Cmdlet       Clear-Item      Clear-Item [-Path] <String[]> [-Force] [-Filter ...
...
Пример 16.1. (html, txt)

По умолчанию командлет Get-Command выводит сведения в трех столбцах: CommandType, Name и Definition. При этом в столбце Definition отображается синтаксис командлетов (многоточие ( ) в столбце синтаксиса указывает на то, что данные обрезаны).

Командлеты могут иметь параметры, к которым можно обратиться по имени, перед которым ставится дефис ( - ), или по позиции (в последнем случае интерпретация параметра будет выполняться в зависимости от его местоположения в командной строке).

Замечание

Косые черты ( / и \ ) вместе с параметрами в оболочке Windows PowerShell не используются.

В общем случае синтаксис командлетов имеет следующую структуру:

имя_командлета –параметр1 -параметр2 аргумент1 аргумент2

Здесь параметр1 – параметр (переключатель), не имеющий значения; параметр2 – имя параметра, имеющего значение аргумент1 ; аргумент2 – параметр, не имеющий имени. Например, командлет Get-Process имеет параметр Name, который определяет имя процесса, информацию о котором нужно вывести. Имя этого параметра указывать необязательно. Таким образом, для получения сведений о процессе Far можно ввести либо команду Get-Process -Name Far, либо команду Get-Process Far.

Автоматическое завершение команд

Находясь в оболочке PowerShell, можно ввести часть какой-либо команды, нажать клавишу <Tab> и система попытается сама завершить эту команду.

Подобное автоматическое завершение срабатывает, во-первых, для имен файлов и путей файловой системы. При нажатии клавиши <Tab> PowerShell автоматически расширит частично введенный путь файловой системы до первого найденного совпадения. При повторении нажатия клавиши <Tab> производится циклический переход по имеющимся возможностям выбора. Также в PowerShell реализована возможность автоматического завершения путей файловой системы на основе шаблонных символов ( ? и * ). Например, если ввести команду cd c:\pro*files и нажать клавишу <Tab>, то в строке ввода появится команда cd 'C:\Program Files'.

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

Наконец, PowerShell позволяет автоматически завершать имена используемых переменных (объектов) и имена свойств объектов .

Псевдонимы команд

Механизм псевдонимов, реализованный в оболочке PowerShell, дает возможность пользователям выполнять команды по их альтернативным именам (например, вместо команды Get-Childitem можно пользоваться псевдонимом dir ). В PowerShell заранее определено много псевдонимов, можно также добавлять собственные псевдонимы в систему.

Псевдонимы в PowerShell делятся на два типа. Первый тип предназначен для совместимости имен с разными интерфейсами. Псевдонимы этого типа позволяют пользователям, имеющим опыт работы с другими оболочками (Cmd.exe или Unix-оболочки), использовать знакомые им имена команд для выполнения аналогичных операций в PowerShell, что упрощает освоение новой оболочки, позволяя не тратить усилий на запоминание новых команд PowerShell. Например, пользователь хочет очистить экран. Если у него есть опыт работы с Cmd.exe, то он, естественно, попробует выполнить команду cls. PowerShell при этом выполнит командлет Clear-Host, для которого cls является псевдонимом и который выполняет требуемое действие – очистку экрана. Для пользователей Cmd.exe в PowerShell определены псевдонимы cd, cls, copy, del, dir, echo, erase, move, popd, pushd, ren, rmdir, sort, type ; для пользователей Unix – псевдонимы cat, chdir, clear, diff, h, history, kill, lp, ls, mount, ps, pwd, r, rm, sleep, tee, write.

Узнать, какой именно командлет скрывается за знакомым псевдонимом, можно с помощью командлета Get-Alias:

PS C:\> Get-Alias cd
CommandType     Name           Definition
-----------     ----           ----------
Alias           cd             Set-Location

Псевдонимы второго типа (стандартные псевдонимы) в PowerShell предназначены для быстрого ввода команд. Такие псевдонимы образуются из имен командлетов, которым они соответствуют. Например, глагол Get сокращается до g, глагол Set сокращается до s, существительное Location сокращается до l и т.д. Таким образом, для командлету Set-Location соответствует псевдоним sl, а командлету Get-Location – псевдоним gl.

Просмотреть список всех пседонимов, объявленных в системе, можно с помощью командлета Get-Alias без параметров. Определить собственный псевдоним можно с помощью командлета Set-Alias.

Справочная система PowerShell

В PowerShell предусмотрено несколько способов получения справочной информации внутри оболочки.

Краткую справку по одному командлету можно получить с помощью параметра ? (вопросительный знак), указанного после имени этого командлета. Например:

PS C:\> get-process -?

ИМЯ
    Get-Process
ОПИСАНИЕ
    Отображает процессы, выполняющиеся на локальном компьютере.

СИНТАКСИС
    Get-Process [[-name] <string[]>] [<CommonParameters>]
    Get-Process -id <Int32[]> [<CommonParameters>]
    Get-Process -inputObject <Process[]> [<CommonParameters>]

ПОДРОБНОЕ ОПИСАНИЕ
    Командлет Get-Process извлекает объект-процесс для каждого процесса. 
    При использовании командлета "Get-Process" без указания параметров 
    происходит отображение всех процессов, выполняющихся на компьютере, 
    что эквивалентно команде "Get-Process *". Процесс можно определить 
    по имени или идентификатору (PID) или передав объект по ковнейеру 
    в командлет Get-Process. Для Get-Process по умолчанию 
    передается имя процесса. Для Stop-Process по умолчанию передается 
    идентификатор процесса.

ССЫЛКИ ПО ТЕМЕ
    Stop-Process

ЗАМЕЧАНИЯ
    Для получения дополнительных сведений введите: 
      "get-help Get-Process -detailed".
    Для получения технических сведений введите: 
      "get-help Get-Process -full".

Более подробную информацию можно получить с помощью специального командлета Get-Help с параметрами Detailed или Full (например, Get-Help Get-Process -Full ). Запустив данный командлет с параметром *, можно увидеть все доступные разделы справочной системы.

Командлет Get-Help позволяет просматривать справочную информацию не только о разных командлетах, но и о синтаксисе языка PowerShell, о псевдонимах, о различных аспектах работы оболочки функциям и т.д. Список тем, обсуждение которых представлено с справочной службе PowerShell, можно увидеть следующим образом:

PS C:\> Get-Help about_*

Name                         Category    Synopsis
----                         --------    --------
about_alias                  HelpFile    Использование альтернативных имен ко...
about_arithmetic_operators   HelpFile    Операторы, которые используются в ко...
about_array                  HelpFile    Компактная структура размещения элем...
about_assignment_operators   HelpFile    Операторы, используемые в оболочке W...
about_associative_array      HelpFile    Компактная структура данных для хран...
about_automatic_variables    HelpFile    Переменные, автоматически задаваемые...
about_break                  HelpFile    Инструкция для немедленного завершен...
about_command_search         HelpFile    Как оболочка Windows PowerShell обна...
about_command_syntax         HelpFile    Формат команд в Windows PowerShell
. . .
Пример 16.2. (html, txt)

Таким образом, чтобы прочитать справочную информацию об использовании массивов в PowerShell, нужно выполнить следующую команду: Get-Help about_array.

Командлет Get-Help выводит содержимое раздела справки на экран сразу целиком. Функции man и help позволяют справочную информацию выводить поэкранно (аналогично команде MORE интерпретатора Cmd.exe), например: man about_array.

Лекция 17. Конвейеризация и управление выводом команд Windows PowerShell

Обсуждается процесс конвейеризации объектов в PowerShell. Рассматриваются процедуры фильтрации и сортировки потока объектов. Описываются командлеты для форматирования выводимых данных и перенаправления выходных потоков команд

Конвейеризация и управление выводом команд Windows PowerShell

Ранее в лекции 2 мы рассматривали понятие конвейеризации (или композиции) команд интерпретатора Cmd.exe, когда выходной поток одной команды перенаправлялся во входной поток другой, объединяя тем самым две команды вместе. Подобные конвейеры команд используются в большинстве оболочек командной строки и являются средством, позволяющим передавать информацию между разными процессами.

Механизм композиции команд представляет собой, вероятно, наиболее ценную концепцию, используемую в интерфейсах командной строки. Конвейеры не только снижают усилия, прилагаемые при вводе сложных команд, но и облегчают отслеживание потока работы в командах. Полезной чертой конвейеров является то, что они не зависят от числа передаваемых элементов, так как конвейер действует на каждый элемент отдельно. Кроме того, каждая команда в конвейере (называемая элементом конвейера) обычно передает свой вывод следующей команде в конвейере, элемент за элементом. Благодаря этому, как правило, снижается потребление ресурсов для сложных команд и возникает возможность получать выводимую информацию немедленно.

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

Конвейеризация объектов в PowerShell

Конвейер в PowerShell – это последовательность команд, разделенных между собой знаком | (вертикальная черта). Каждая команда в конвейере получает объект от предыдущей команды, выполняет определенные операции над ним и передает следующей команде в конвейере. С точки зрения пользователя, объекты упаковывают связанную информацию в форму, в которой информацией проще манипулировать как единым блоком и из которой при необходимости извлекаются определенные элементы.

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

При передаче по конвейеру объектов этой проблемы не возникает, здесь нужная информация извлекается из элемента конвейера простым обращением к соответствующему свойству объекта. Однако теперь возникает новый вопрос: каким образом узнать, какие именно свойства есть у объектов, передаваемых по конвейеру? Ведь при выполнении того или иного командлета мы на экране видим только одну или несколько колонок отформатированного текста. Например, запустим командлет Get-Process, который выводит информацию о запущенных в системе процессах:

PS C:\> Get-Process

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    158      11    45644      22084   126   159.69   2072 AcroRd32
     98       5     1104        284    32     0.10    256 alg
     39       1      364        364    17     0.26   1632 ati2evxx
     57       3     1028        328    30     0.38    804 atiptaxx
    434       6     2548       3680    27    21.96    800 csrss
     64       3      812        604    29     0.22   1056 ctfmon
    364      11    14120       9544    69    11.82    456 explorer
     24       2     1532       2040    29     5.34   2532 Far

Фактически на экране мы видим только сводную информацию (результат форматирования полученных данных), а не полное представление выходного объекта. Из этой информации не понятно, сколько точно свойств имеется у объектов, генерируемых командой Get-Process, и какие имена имеют эти свойства. Например, мы хотим найти все "зависшие" процессы, которые не отвечают на запросы системы. Можно ли это сделать с помощью командлета Get-Process, какое свойство нужно проверять у выводимых объектов?

Для ответа на подобные вопросы нужно, прежде всего, научиться исследовать структуру объектов PowerShell, узнавать, какие свойства и методы имеются у этих объектов.

Просмотр структуры объектов

Для анализа структуры объекта, возвращаемого определенной командой, проще всего направить этот объект по конвейеру на командлет Get-Member (псевдоним gm ), например:

PS C:\> Get-Process | Get-Member

   TypeName: System.Diagnostics.Process

Name                    MemberType     Definition
----                    ----------     ----------
Handles                 AliasProperty  Handles = Handlecount
Name                    AliasProperty  Name = ProcessName
NPM                     AliasProperty  NPM = NonpagedSystemMemorySize
PM                      AliasProperty  PM = PagedMemorySize
VM                      AliasProperty  VM = VirtualMemorySize
WS                      AliasProperty  WS = WorkingSet
. . .
Responding              Property       System.Boolean Responding {get;}
. . .

Здесь мы видим имя .NET-класса, экземпляры которого возвращаются в ходе работы исследуемого командлета (в нашем примере это класс System.Diagnostic.Process), а также полный список элементов объекта (в частности, интересующее нас свойство Responding, определяющего "зависшие" процессы). При этом на экран выводится очень много элементов, просматривать их неудобно. Командлет Get-Member позволяет перечислить только те элементы объекта, которые являются его свойствами. Для этого используется параметр MemberType со значением Properties:

PS C:\> Get-Process | Get-Member -MemberType Property

   TypeName: System.Diagnostics.Process

Name                       MemberType Definition
----                       ---------- ----------
BasePriority               Property   System.Int32 BasePriority {get;}
Container                  Property   System.ComponentModel.IContainer...
EnableRaisingEvents        Property   System.Boolean EnableRaisingEvents...
ExitCode                   Property   System.Int32 ExitCode {get;}
ExitTime                   Property   System.DateTime ExitTime {get;}
Handle                     Property   System.IntPtr Handle {get;}
HandleCount                Property   System.Int32 HandleCount {get;}
HasExited                  Property   System.Boolean HasExited {get;}
Id                         Property   System.Int32 Id {get;}
MachineName                Property   System.String MachineName {get;}
. . . 
Responding                 Property   System.Boolean Responding {get;}
. . .

Как мы видим, процессам операционной системы соответствуют объекты, имеющие очень много свойств, на экран же при работе командлета Get-Process выводятся лишь несколько из них (способы отображения объектов различных типов задаются конфигурационными файлами в формате XML, находящимися в каталоге, где установлен файл powershell.exe).

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

Фильтрация объектов в конвейере

В PowerShell поддерживается возможность фильтрации объектов в конвейере, т.е. удаление из конвейера объектов, не удовлетворяющих определенному условию. Данную функциональность обеспечивает командлет Where-Object, позволяющий проверить каждый объект, находящийся в конвейере, и передать его дальше по конвейеру, только если объект удовлетворяет условиям проверки.

Например, для вывода информации о "зависших" процессах (объекты, возвращаемые командлетом Get-Process, у которых свойство Responding равно False ) можно использовать следующий конвейер:

Get-Process | Where-Object {-not $_.Responding}

Другой пример – оставим в конвейере только те процессы, у которых значение идентификатора (свойство Id ) больше 1000:

Get-Process | Where-Object {$_.Id -gt 1000}

В блоках сценариев командлета Where-Object для обращения к текущему объекту конвейера и извлечения нужных свойств этого объекта используется специальная переменная $_, которая создается оболочкой PowerShell автоматически. Данная переменная используется и в других командлетах, производящих обработку элементов конвейера.

Условие проверки в Where-Object задается в виде блока сценария – одной или нескольких команд PowerShell, заключенных в фигурные скобки {}. Результатом выполнения данного блока сценария должно быть значение логического типа: True (истина) или False (ложь). Как можно понять из примеров, в блоке сценария используются специальные операторы сравнения.

Замечание

В PowerShell для операторов сравнения не используются обычные символы > или <, так как в командной строке они обычно означают перенаправление ввода/вывода.

Основные операторы сравнения приведены в табл. 17.1.

Таблица 17.1. Операторы сравнения в PowerShell
Оператор Значение Пример (возвращается значение True)
-eqравно10 -eq 10
-neне равно9 -ne 10
-ltменьше3 -lt 4
-leменьше или равно3 –le 4
-gtбольше4 -gt 3
-geбольше или равно4 -ge 3
-likeсравнение на совпадение с учетом подстановочного знака в тексте"file.doc" –like "f*.doc"
-notlikeсравнение на несовпадение с учетом подстановочного знака в тексте"file.doc" –notlike "f*.rtf"
-containsсодержит1,2,3 –contains 1
-notcontainsне содержит1,2,3 –notcontains 4

Операторы сравнения можно соединять друг с другом с помощью логических операторов (см. табл. 17.2).

Таблица 17.2. Логически операторы в PowerShell
Оператор Значение Пример (возвращается значение True)
-andлогическое И(10 -eq 10) –and (1 –eq 1)
-orлогическое ИЛИ(9 -ne 10) –or (3 –eq 4)
-notлогическое НЕ-not (3 –gt 4)
!логическое НЕ!(3 -gt 4)
Сортировка объектов

Сортировка элементов конвейера – еще одна операция, которая часто применяется при конвейерной обработке объектов. Данную операцию осуществляет командлет Sort-Object: ему передаются имена свойств, по которым нужно произвести сортировку, а он возвращает данные, упорядоченные по значениям этих свойств.

Например, для вывода списка запущенных в системе процессов, упорядоченного по затраченному процессорному времени (свойство cpu ), можно воспользоваться следующим конвейером:

PS C:\> Get-Process | Sort-Object cpu

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
      0       0        0         16     0               0 Idle
     36       2      728         32    23     0.05   1792 klswd
     98       5     1104        764    32     0.09    252 alg
     21       1      164         60     4     0.09    748 smss
     30       2      672        724    27     0.11   1700 WinCinemaMgr
     39       1      364        464    17     0.12   1644 ati2evxx
    163       6     1536       1404    35     0.12   1612 svchost
     55       3     1088        852    27     0.14   1220 svchost
     22       2      504        712    23     0.14    772 winampa
    120       4     2364       1228    35     0.26   1876 svchost
    170       5     4516        796    44     0.27   1260 GoogleToolbarNotifier
    193       5     2916       1488    59     0.29   1040 svchost
     64       3      812       1080    29     0.30   1252 ctfmon
    140       5     3208       1220    41     0.32   1524 spoolsv
    281      14     1764       1688    37     0.34   1120 svchost
     57       3     1028        996    30     0.39    932 atiptaxx
    503      52     7296       3596    51     2.47    836 winlogon
    259       6     1432       1340    19     2.48    880 services
    341       8     3572       1856    40     5.36    892 lsass
    240     158    29536      10388   175     5.58   1780 outpost
    149       4     2940       1108    41     9.29   1248 kav
    398       5    36140      26408   137     9.97   1984 powershell
    375      12    15020      10456    75    14.03   1116 explorer
    376       0        0         36     2    14.97      4 System
    409       6     2500       3192    26    20.10    812 csrss
   1513      54    13528       9800    95    25.78   1156 svchost
    717      75    37432        704   145    56.97   1748 kavsvc
    152       4     2372       2716    38    58.09   2028 wmiprvse
    307      13    10952      27080   173  9128.03   1200 WINWORD
Пример 17.1. (html, txt)

Для сортировки в обратном порядке используется параметр Descending:

PS C:\> Get-Process | Sort-Object cpu -Descending

Handles  NPM(K)    PM(K)      WS(K) VM(M)   CPU(s)     Id ProcessName
-------  ------    -----      ----- -----   ------     -- -----------
    307      13    10956      27040   173  9152.23   1200 WINWORD
    152       4     2372       2716    38    59.19   2028 wmiprvse
    717      75    37432       1220   145    57.15   1748 kavsvc
   1524      54    13528       9800    95    26.13   1156 svchost
    410       6     2508       3224    26    20.62    812 csrss
    376       0        0         36     2    15.11      4 System
    377      13    15020      10464    75    14.20   1116 explorer
    374       5    36484      26828   137    10.53   1984 powershell
    149       4     2940       1108    41     9.34   1248 kav
    240     158    29536      10388   175     5.61   1780 outpost
    344       8     3572       1856    40     5.40    892 lsass
    512      53     7324       3608    51     2.51    836 winlogon
    259       6     1432       1340    19     2.48    880 services
     57       3     1028        996    30     0.39    932 atiptaxx
    281      14     1764       1688    37     0.34   1120 svchost
    140       5     3208       1220    41     0.32   1524 spoolsv
     64       3      812       1080    29     0.30   1252 ctfmon
    193       5     2916       1488    59     0.29   1040 svchost
    170       5     4516        796    44     0.27   1260 GoogleToolbarNotifier
    120       4     2364       1228    35     0.26   1876 svchost
     22       2      504        712    23     0.15    772 winampa
     55       3     1088        852    27     0.14   1220 svchost
     39       1      364        464    17     0.13   1644 ati2evxx
    163       6     1536       1404    35     0.12   1612 svchost
     30       2      672        724    27     0.11   1700 WinCinemaMgr
     21       1      164         60     4     0.09    748 smss
     98       5     1104        764    32     0.09    252 alg
     36       2      728         32    23     0.05   1792 klswd
      0       0        0         16     0               0 Idle
Пример 17.2. (html, txt)

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

Get-Process | Where-Object {$_.Id -gt 1000} | Sort-Object cpu -Descending

Управление выводом команд в PowerShell

Работая в оболочке PowerShell, мы пока не задумывались, каким образом система формирует строки текста, которые выводятся на экран в результате выполнения той или иной команды (напомним, что командлеты PowerShell возвращают .NET-объекты, которые, как правило, не знают, каким образом отображать себя на экране).

На самом деле в PowerShell имеется база данных (набор XML-файлов), содержащая модули форматирования по умолчанию для различных типов .NET-объектов. Эти модули определяют, какие свойства объекта отображаются при выводе и в каком формате: списка или таблицы. Когда объект достигает конца конвейера, PowerShell определяет его тип и ищет его в списке объектов, для которых определено правило форматирования. Если данный тип в списке обнаружен, то к объекту применяется соответствующий модуль форматирования; если нет, то PowerShell просто отображает свойства этого .NET-объекта.

Также в PowerShell можно явно задавать правила форматирования данных, выводимых командлетами, и подобно командному интерпретатору Cmd.exe перенаправлять эти данные в файл, на принтер или в пустое устройство.

Форматирование выводимой информации

В традиционных оболочках команды и утилиты сами форматируют выводимые данные. Некоторые команды (например, dir в интерпретаторе Cmd.exe) позволяют настраивать формат вывода с помощью специальных параметров.

В оболочке PowerShell вывод форматируют только четыре специальных командлета Format (табл. 17.3). Это упрощает изучение, так как не нужно запоминать средства и параметры форматирования для других команд (остальные командлеты вывод не форматируют).

Таблица 17.3. Командлеты PowerShell для форматирования вывода
Командлет Описание
Format-TableФорматирует вывод команды в виде таблицы, столбцы которой содержат свойства объекта (также могут быть добавлены вычисляемые столбцы). Поддерживается возможность группировки выводимых данных
Format-ListВывод форматируется как список свойств, в котором каждое свойство отображается на новой строке. Поддерживается возможность группировки выводимых данных
Format-CustomДля форматирования вывода используется пользовательское представление (view)
Format-WideФорматирует объекты в виде широкой таблицы, в которой отображается только одно свойство каждого объекта

Как уже отмечалось выше, если ни один из командлетов Format явно не указан, то используется модуль форматирования по умолчанию, который определяется по типу отображаемых данных. Например, при выполнении командлета Get-Service данные по умолчанию выводятся как таблица с тремя столбцами (Status, Name и DisplayName):

PS C:\> Get-Service

Status   Name               DisplayName
------   ----               -----------
Stopped  Alerter            Оповещатель
Running  ALG                Служба шлюза уровня приложения
Stopped  AppMgmt            Управление приложениями
Stopped  aspnet_state       ASP.NET State Service
Running  Ati HotKey Poller  Ati HotKey Poller
Running  AudioSrv           Windows Audio
Running  BITS               Фоновая интеллектуальная служба пер...
Running  Browser            Обозреватель компьютеров
Stopped  cisvc              Служба индексирования
Stopped  ClipSrv            Сервер папки обмена
Stopped  clr_optimizatio... .NET Runtime Optimization Service v...
Stopped  COMSysApp          Системное приложение COM+
Running  CryptSvc           Службы криптографии
Running  DcomLaunch         Запуск серверных процессов DCOM
Running  Dhcp               DHCP-клиент
...

Для изменения формата выводимых данных нужно направить их по конвейеру соответствующему командлету Format. Например, следующая команда выведет список служб с помощью командлета Format-List:

PS C:\> Get-Service | Format-List

Name                : Alerter
DisplayName         : Оповещатель
Status              : Stopped
DependentServices   : {}
ServicesDependedOn  : {LanmanWorkstation}
CanPauseAndContinue : False
CanShutdown         : False
CanStop             : False
ServiceType         : Win32ShareProcess

Name                : ALG
DisplayName         : Служба шлюза уровня приложения
Status              : Running
DependentServices   : {}
ServicesDependedOn  : {}
CanPauseAndContinue : False
CanShutdown         : False
CanStop             : True
ServiceType         : Win32OwnProcess
. . .

Как мы видим, при использовании формата списка выводится больше сведений о каждой службе, чем в формате таблицы (вместо трех столбцов данных о каждой службе в формате списка выводятся девять строк данных). Однако это вовсе не означает, что командлет Format-List извлекает дополнительные сведения о службах. Эти данные содержатся в объектах, возвращаемых командлетом Get-Service, однако командлет Format-Table, используемый по умолчанию, отбрасывает их, потому что не может вывести на экран более трех столбцов.

При форматировании вывода с помощью командлетов Format-List и Format-Table можно указывать имена свойства объекта, которые должны быть отображены (напомним, что просмотреть список свойств, имеющихся у объекта, позволяет рассмотренный ранее командлет Get-Member ). Например:

PS C:\> Get-Service | Format-List Name, Status, CanStop

Name    : Alerter
Status  : Stopped
CanStop : False

Name    : ALG
Status  : Running
CanStop : True

Name    : AppMgmt
Status  : Stopped
CanStop : False
. . .

Вывести все имеющиеся у объектов свойства можно с помощью параметра *, например:

PS C:\> Get-Service | Format-table *
Перенаправление выводимой информации

В оболочке PowerShell имеются несколько командлетов, с помощью которых можно управлять выводом данных. Эти командлеты начинаются со слова Out, их список можно увидеть следующим образом:

PS C:\> Get-Command out-* | Format-Table Name

Name
----
Out-Default
Out-File
Out-Host
Out-Null
Out-Printer
Out-String

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

Параметр Paging командлета Out-Host, подобно команде more интерпретатора Cmd.exe, позволяет организовать постраничный вывод информации, например:

Get-Help Get-Process –Full | Out-Host -Paging
Сохранение данных в файл

Командлет Out-File позволяет направить выводимые данные вместо окна консоли в текстовый файл. Аналогичную задачу решает оператор перенаправления (>), однако командлет Out-File имеет несколько дополнительных параметров, с помощью которых можно более гибко управлять выводом: задавать тип кодировки файла (параметр Encoding ), задавать длину выводимых строк в знаках (параметр Width ), выбирать режим перезаписи файла (параметры Append, noClobber ). Например, следующая команда направит информацию о зарегистрированных на компьютере службах в файл C:\service.txt, причем данный файл будет записан в формате ASCII:

Get-Process | Out-File -FilePath C:\Process.txt -Encoding ASCII
Печать данных

Данные можно вывести непосредственно на принтер с помощью командлета Out-Printer. При этом печать может производиться как на принтере по умолчанию (никаких специальных параметров для этого указывать не нужно), так и на произвольном принтере (в этом случае отображаемое имя принтера должно быть указано в качестве значения параметра Name ). Например:

PS C:\script> Get-Process | Out-Printer -Name "Xerox Phaser 3500 PCL 6"
Подавление вывода

Командлет Out-Null служит для отбрасывания любых своих входных данных. Это может пригодиться для подавления вывода на экран ненужных сведений, полученных в качестве побочного эффекта выполнения какой-либо команды. Например, при создании каталога командой mkdir на экран выводится его содержимое:

PS C:\> mkdir klop

    Каталог: Microsoft.PowerShell.Core\FileSystem::C:\


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
d----        03.12.2007      1:01            klop

Если вы не желаете видеть эту информацию, то результат выполнения команды mkdir нужно передать по конвейеру командлету Out-Null:

mkdir klop | Out-Null

Лекция 18. Работа в Windows PowerShell с объектными моделями WMI, COM и .NET

Описывается доступ из PowerShell к внешним объектам WMI, COM и .NET. Обсуждается вызов статических методов .NET-классов. Приводятся примеры использования объектов WSH, взаимодействия с приложением Microsoft Word

Работа в Windows PowerShell с объектными моделями WMI, COM и .NET

Одна из основных задач, для решения которых создавалась оболочка PowerShell, было получение из командной строки доступа к различным объектным инфраструктурам, поддерживаемым операционной системой Windows. Раньше к подобным объектам можно было обращаться либо из полноценных приложений с помощью интерфейса прикладного программирования (API), либо из сценариев WSH. В любом случае для использования внешних объектов приходилось писать программный код и изучать их структуру, что значительно затрудняло работу с ними и препятствовало широкому распространению технологий автоматизации среди системных администраторов и пользователей Windows.

Для решения этой проблемы в PowerShell были разработаны специальные командлеты, позволяющие в интерактивном режиме из оболочки обращаться к объектам WMI, COM и .NET.

Доступ к WMI

В предыдущих лекциях мы уже обращались к объектам WMI из сценариев на языках VBScript и JScript, а также из оболочки WMIC. В PowerShell экземпляры объектов WMI можно получать с помощью командлета Get-WmiObject.

Подключение к подсистеме WMI. Получение списка классов

Для обращения к определенному объекту WMI нужно знать наименование класса, к которому он относится (например, Win32_Process или Win32_Service ). PowerShell позволяет в интерактивном режиме получить список всех классов WMI на локальном или удаленном компьютере. Для этого нужно выполнить командлет Get-WmiObject с параметром List:

PS C:\> Get-WmiObject -List

__SecurityRelatedClass                                      __NTLMUser9X
__PARAMETERS                                                __SystemSecurity
__NotifyStatus                                              __ExtendedStatus
Win32_PrivilegesStatus                                      Win32_TSNetworkAdapterSettingError
Win32_TSRemoteControlSettingError                           Win32_TSEnvironmentSettingError
Win32_TSSessionDirectoryError                               Win32_TSLogonSettingError
Win32_TerminalError                                         Win32_JobObjectStatus
Win32_TerminalServiceSettingError                           Win32_TSPermissionsSettingError
Win32_TSClientSettingError                                  Win32_TSGeneralSettingError
Win32_TSSessionSettingError                                 __SystemClass
. . .
Пример 18.1. (html, txt)

В данном примере выводится список классов WMI на локальном компьютере. Если вам нужно подключиться к подсистеме WMI другой машине, то ее имя или IP-адрес нужно указать в качестве значения параметром ComputerName, например:

PS C:\> Get-WmiObject –ComputerName 10.169.1.15 -List

__SecurityRelatedClass                                      __NTLMUser9X
__PARAMETERS                                                __SystemSecurity
__NotifyStatus                                              __ExtendedStatus
Win32_PrivilegesStatus                                      Win32_TSNetworkAdapterSettingError
Win32_TSRemoteControlSettingError                           Win32_TSEnvironmentSettingError
. . . 
PS C:\> Get-WmiObject –ComputerName Comp1 -List

__SecurityRelatedClass                                      __NTLMUser9X
__PARAMETERS                                                __SystemSecurity
__NotifyStatus                                              __ExtendedStatus
Win32_PrivilegesStatus                                      Win32_TSNetworkAdapterSettingError
Win32_TSRemoteControlSettingError                           Win32_TSEnvironmentSettingError
. . .
Пример 18.2. (html, txt)

По умолчанию командлет Get-WmiObject подключается к пространству имен Root\CIMV2. Сменить это пространство имен позволяет параметр Namespace, в качестве значения которого указывается нужное наименование. Например:

PS C:\> Get-WmiObject -Namespace Root -List

__SecurityRelatedClass                                      __NTLMUser9X
__PARAMETERS                                                __SystemSecurity
__NotifyStatus                                              __ExtendedStatus
__SystemClass                                               __Provider
__Win32Provider                                             __thisNAMESPACE
__IndicationRelated                                         __EventGenerator
. . .
Пример 18.3. (html, txt)
Получение объектов WMI

Зная имя класса WMI, получить экземпляры этого класса очень просто. Например:

PS C:\> Get-WmiObject Win32_Service

ExitCode  : 1077
Name      : Alerter
ProcessId : 0
StartMode : Disabled
State     : Stopped
Status    : OK

ExitCode  : 0
Name      : ALG
ProcessId : 564
StartMode : Manual
State     : Running
Status    : OK
. . .
Пример 18.4. (html, txt)

Данная команда выводит информацию о службах, зарегистрированных в системе. На самом деле объекты класса Win32_Service имеют намного больше свойств, чем по умолчанию отображается на экране; увидеть список всех свойств и методов объекта WMI можно, как и в случае .NET-объектов, с помощью командлета Get-Member:

PS C:\> Get-WmiObject Win32_Service | Get-Member

   TypeName: System.Management.ManagementObject#root\cimv2\Win32_Service

Name                    MemberType   Definition
----                    ----------   ----------
Change                  Method       System.Management.ManagementBaseObject Chang…
ChangeStartMode         Method       System.Management.ManagementBaseObject Chang…
Create                  Method       System.Management.ManagementBaseObject Creat…
InterrogateService      Method       System.Management.ManagementBaseObject Inter…
PauseService            Method       System.Management.ManagementBaseObject Pause…
ResumeService           Method       System.Management.ManagementBaseObject Resum…
StartService            Method       System.Management.ManagementBaseObject Start…
StopService             Method       System.Management.ManagementBaseObject StopS…
UserControlService      Method       System.Management.ManagementBaseObject UserC…
AcceptPause             Property     System.Boolean AcceptPause {get;set;}
AcceptStop              Property     System.Boolean AcceptStop {get;set;}
Caption                 Property     System.String Caption {get;set;}
CheckPoint              Property     System.UInt32 CheckPoint {get;set;}
CreationClassName       Property     System.String CreationClassName {get;set;}
Description             Property     System.String Description {get;set;}
DesktopInteract         Property     System.Boolean DesktopInteract {get;set;}
DisplayName             Property     System.String DisplayName {get;set;}
ErrorControl            Property     System.String ErrorControl {get;set;}
. . .
Пример 18.5. (html, txt)

Используя командлеты форматирования, можно выводить на экран интересующие нас свойства, например:

PS C:\> Get-WmiObject Win32_Service | Format-Table Name, 
  AcceptStop

Name                           AcceptStop
----                           ----------
Alerter                             False
ALG                                  True
AppMgmt                             False
aspnet_state                        False
Ati HotKey Poller                   False
AudioSrv                             True
BITS                                 True
Browser                              True
cisvc                               False
ClipSrv                             False
clr_optimization_v2.0.50727_32      False
COMSysApp                           False
CryptSvc                             True
DcomLaunch                          False
Dhcp                                 True
dmadmin                             False
dmserver                            False
Dnscache                             True
ERSvc                                True
. . .
Пример 18.6. (html, txt)
Выполнение WQL-запросов

Параметр Query командлета Get-WmiObject позволяет выполнять произвольные запросы на языке WQL. Например:

PS C:\> Get-WmiObject -Query 'select * from win32_process 
  where name="lsass.exe"'

ProcessName                : lsass.exe
Handles                    : 358
VM                         : 42233856
WS                         : 1511424
Path                       : C:\WINDOWS.1\system32\lsass.exe
__GENUS                    : 2
__CLASS                    : Win32_Process
__SUPERCLASS               : CIM_Process
__DYNASTY                  : CIM_ManagedSystemElement
__RELPATH                  : Win32_Process.Handle="884"
__PROPERTY_COUNT           : 45
. . .
Пример 18.7. (html, txt)

Работа с COM-объектами

В PowerShell имеется командлет New-Object, позволяющий создавать экземпляры внешних COM-объектов (в частности, можно обращаться к знакомым нам объектам WSH, серверам автоматизации из пакета Microsoft Office или браузеру Internet Explorer). Отметим, что "общение" с COM-объектами в оболочке происходит с помощью соответствующих механизмов .NET Framework (создаются экземпляры .NET-класса System.__ComObject ), поэтому на командлет New-Object действуют те же ограничения, какие действуют на платформу .NET во время вызова COM-объектов.

Для создания экземпляра COM-объекта нужно указать его программный идентификатор (ProgID) в качестве значения параметра ComObject, например:

PS C:\> New-Object -ComObject WScript.Shell

SpecialFolders                   CurrentDirectory
--------------                     ----------------
{C:\Documents and Settings\All Users\Рабочий стол, ... 	
  C:\Documents and Settings\User
Пример 18.8. (html, txt)

Перенаправив созданный объект по конвейеру на командлет Get-Member, можно увидеть список всех свойств и методов, имеющихся в COM-объекте:

PS C:\> New-Object -ComObject WScript.Shell | Get-Member

   TypeName: System.__ComObject#{41904400-be18-11d3-a28b-00104bd35090}

Name                     MemberType            Definition
----                     ----------            ----------
AppActivate              Method                bool AppActivate (Variant, Variant)
CreateShortcut           Method                IDispatch CreateShortcut (string)
Exec                     Method                IWshExec Exec (string)
ExpandEnvironmentStrings Method                string ExpandEnvironmentStrings (string)
LogEvent                 Method                bool LogEvent (Variant, string, string)
Popup                    Method                int Popup (string, Variant, Variant, Variant)
RegDelete                Method                void RegDelete (string)
RegRead                  Method                Variant RegRead (string)
RegWrite                 Method                void RegWrite (string, Variant, Variant)
Run                      Method                int Run (string, Variant, Variant)
SendKeys                 Method                void SendKeys (string, Variant)
Environment              ParameterizedProperty IWshEnvironment Environment (Variant) {get}
CurrentDirectory         Property              string CurrentDirectory () {get} {set}
SpecialFolders           Property              IWshCollection SpecialFolders () {get}
Пример 18.9. (html, txt)

Как же теперь воспользоваться методами данного COM-объекта? Для этого удобнее всего сохранить ссылку на объект в переменной, это позволит обращаться к нему в любое время до окончания сеанса работы в PowerShell.

Сохранение объектов в переменных

Оболочка PowerShell поддерживает работу с переменными, которые, по сути, являются именованными объектами. В переменной можно сохранить вывод любой допустимой команды PowerShell. Имена переменных всегда начинаются с знака доллара ( $ ).

Для сохранения в переменной ссылки на COM-объект нужно выполнить следующую команду:

$Shell=New-Object -ComObject WScript.Shell

Убедимся, что в переменной $Shell на самом деле хранится экземпляр COM-объекта с программным идентификатором WScript.Shell:

PS C:\> $Shell | Get-Member

   TypeName: System.__ComObject#{41904400-be18-11d3-a28b-00104bd35090}

Name                     MemberType            Definition
----                     ----------            ----------
AppActivate              Method                bool AppActivate (Variant, Variant)
CreateShortcut           Method                IDispatch CreateShortcut (string)
Exec                     Method                IWshExec Exec (string)
ExpandEnvironmentStrings Method                string ExpandEnvironmentStrings (string)
LogEvent                 Method                bool LogEvent (Variant, string, string)
Popup                    Method                int Popup (string, Variant, Variant, Variant)
RegDelete                Method                void RegDelete (string)
RegRead                  Method                Variant RegRead (string)
RegWrite                 Method                void RegWrite (string, Variant, Variant)
Run                      Method                int Run (string, Variant, Variant)
SendKeys                 Method                void SendKeys (string, Variant)
Environment              ParameterizedProperty IWshEnvironment Environment (Variant) {get}
CurrentDirectory         Property              string CurrentDirectory () {get} {set}
SpecialFolders           Property              IWshCollection SpecialFolders () {get}
Пример 18.10. (html, txt)
Пример: создание ярлыка на рабочем столе

С помощью COM-объекта WScript.Shell можно быстро создавать ярлыки для папок и файлов. Для примера мы создадим на рабочем столе активного пользователя ярлык PSHome.lnk для папки, в которой установлена оболочка PowerShell.

Сначала создадим экземпляр COM-объекта WScript.Shell и сохраним ссылку на него в переменной $Shell:

PS C:\> $Shell = new-object -comobject WScript.Shell

У данного объекта имеется метод CreateShortcut, в качестве параметра которого нужно указывать путь к создаваемому ярлыку. Путь к рабочему столу можно определить разными способами, например, с помощью переменной определенной в PowerShell переменной $Home, в которой хранится путь к личной папке активного пользователя:

PS C:\> $Home
C:\Documents and Settings\User

По умолчанию содержимое рабочего стола хранится в подкаталоге "Рабочий стол" личной папки пользователя, поэтому для создания ярлыка выполним следующую команду:

PS C:\> $lnk = $Shell.CreateShortcut("$Home\Рабочий стол\PSHome.lnk")

Здесь нужно учесть, что для получения значения переменной (в нашем случае $Home) ее имя нужно указывать внутри двойных кавычек, а не в одинарных.

Посмотрим, какие свойства и методы имеет объект, сохраненный в переменной $lnk:

PS C:\> $lnk | Get-Member

   TypeName: System.__ComObject#{f935dc23-1cf0-11d0-adb9-00c04fd58a0b}

Name             MemberType Definition
----             ---------- ----------
Load             Method     void Load (string)
Save             Method     void Save ()
Arguments        Property   string Arguments () {get} {set}
Description      Property   string Description () {get} {set}
FullName         Property   string FullName () {get}
Hotkey           Property   string Hotkey () {get} {set}
IconLocation     Property   string IconLocation () {get} {set}
RelativePath     Property    {get} {set}
TargetPath       Property   string TargetPath () {get} {set}
WindowStyle      Property   int WindowStyle () {get} {set}
WorkingDirectory Property   string WorkingDirectory () {get} {set}
Пример 18.11. (html, txt)

Для создания ярлыка на папку достаточно сохранить путь к ней в свойстве TargetPath и вызвать метод Save для сохранения ярлыка. Путь к домашней папке PowerShell хранится в специальной переменной $PSHome, поэтому выполняем следующие команды:

PS C:\> $lnk.TargetPath = $PSHome
PS C:\> $lnk.Save()

Задача решена.

Пример: вывод текста в Microsoft Word

Ранее мы уже рассматривали сценарий WSH на языке VBScript, который управляет приложением Microsoft Word (см. листинг 7.12). Решим аналогичную задачу в PowerShell: запустим из оболочки Microsoft Word и напечатаем в нем строку текста.

Сделать это несложно. Сначала создаем экземпляр главного объекта сервера автоматизации Microsoft Word, который имеет программный идентификатор "Word.Application", и сохраняем ссылку на этот объект в переменной $word::

PS C:\> $word = new-object -comobject Word.Application

Создаем новый документ (метод Add коллекции Documents ) и сохраняем ссылку на документ в переменной $doc:

PS C:\> $doc = $word.Documents.Add()

Делаем окно с новым документом видимым:

PS C:\> $word.Visible = $true

Наконец, печатаем строку текста:

PS C:\> $word.Selection.TypeText("Привет!" )

Использование .NET-объектов. Вызов статических методов

Оболочка PowerShell базируется на платформе .NET и позволяет использовать все ее возможности из командной строки. В частности, тот же командлет New-Object, с помощью которого мы работали с объектами WMI и COM, позволяет создавать экземпляры .NET-объектов. Этой возможностью можно воспользоваться в случае, если для решения определенной задачи не удается найти подходящий командлет PowerShell, но существует .NET-объект, который обладает нужной функциональностью. Например, большинство командлетов PowerShell 1.0 не поддерживают работу с удаленными компьютерами, в частности нельзя управлять журналами событий операционной системы на удаленном компьютере. Однако можно в оболочке создать экземпляр .NET-объекта System.Diagnostics.EventLog, сопоставив его с журналом событий на определенном компьютере и воспользоваться методами этого объекта для очистки журнала или настройки параметров протоколирования событий.

Также в .NET имеются классы, экземпляры которых нельзя создать с помощью командлета New-Object. Такие классы называются статическими, так как они не создаются, не уничтожаются и не меняются. В частности, статическим является класс System.Math, методы которого часто используются для математических вычислений.

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

PS C:\> [System.Math]

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    Math                                     System.Object

Методы статического класса также называются статическими. Для просмотра статических методов класса нужно передать имя этого класса (в квадратных скобках) по конвейеру командлету Get-Member с параметром Static:

PS C:\> [System.Math] | Get-Member -Static

   TypeName: System.Math

Name            MemberType Definition
----            ---------- ----------
Abs             Method     static System.Single Abs(Single value), stati. . .
Acos            Method     static System.Double Acos(Double d)
Asin            Method     static System.Double Asin(Double d)
Atan            Method     static System.Double Atan(Double d)
Atan2           Method     static System.Double Atan2(Double y, Double x. . .
BigMul          Method     static System.Int64 BigMul(Int32 a, Int32 b)
Ceiling         Method     static System.Double Ceiling(Double a), stati. . .
Cos             Method     static System.Double Cos(Double d)
Cosh            Method     static System.Double Cosh(Double value)
DivRem          Method     static System.Int32 DivRem(Int32 a, Int32 b, . . .
Equals          Method     static System.Boolean Equals(Object objA, Obj. . .
Exp             Method     static System.Double Exp(Double d)
Floor           Method     static System.Double Floor(Double d), static. . .
IEEERemainder   Method     static System.Double IEEERemainder(Double x, . . .
Log             Method     static System.Double Log(Double d), static Sy. . .
Log10           Method     static System.Double Log10(Double d)
Max             Method     static System.SByte Max(SByte val1, SByte val. . .
Min             Method     static System.SByte Min(SByte val1, SByte val. . .
Pow             Method     static System.Double Pow(Double x, Double y)
ReferenceEquals Method     static System.Boolean ReferenceEquals(Object. . .
Round           Method     static System.Double Round(Double a), static. . .
Sign            Method     static System.Int32 Sign(SByte value), static. . .
Sin             Method     static System.Double Sin(Double a)
Sinh            Method     static System.Double Sinh(Double value)
Sqrt            Method     static System.Double Sqrt(Double d)
Tan             Method     static System.Double Tan(Double a)
Tanh            Method     static System.Double Tanh(Double value)
Truncate        Method     static System.Decimal Truncate(Decimal d), st. . .
E               Property   static System.Double E {get;}
PI              Property   static System.Double PI {get;}
Пример 18.12. (html, txt)

Как мы видим, методы класса System.Math реализуют различные математические функции, их легко распознать по названию.

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

PS C:\> $a=[System.Math]::Sqrt(25)
PS C:\> $a
5

Лекция 19. Сценарии Windows PowerShell

Описываются управляющие инструкции языка PowerShell (ветвления и циклы). Обсуждаются механизмы безопасности, применяемые при запуске сценариев PowerShell

Сценарии Windows PowerShell

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

Сценарии PowerShell представляют собой текстовые файлы с расширением ps1, в которых записаны команды, операторы и другие конструкции языка PowerShell. В отличие от сценариев WSH и командных файлов интерпретатора Cmd.exe, сценарии PowerShell можно писать поэтапно, непосредственно в самой оболочке, перенося затем готовый код во внешний текстовый файл. Такой подход значительно упрощает изучение языка и отладку сценариев, так как можно сразу видеть результат выполнения отдельных частей сценария.

Как правило, при создании более-менее сложных сценариев возникает необходимость в управлении ходом выполнения программы. Для этого в языке PowerShell, как и в любом алгоритмическом языке, предусмотрены специальные инструкции.

Управляющие инструкции языка PowerShell

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

Инструкция If … Elseif … Else

Логические сравнения лежат в основе практически всех алгоритмических языков программирования. В PowerShell при помощи инструкции If можно выполнять определенные блоки кода только в том случае, когда заданное условие имеет значение True (истина). Также можно задать одно или несколько дополнительных условий выполнения, если все предыдущие условия имели значение False. Наконец, можно задать дополнительный блок кода, который будет выполняться в том случае, если ни одно из условий не имеет значения True.

Синтаксис инструкции If в общем случае имеет следующий вид:

if (условие1)
   {блок_кода1}
[elseif (условие2)
    {блок_кода2}]
[else
   {блок_кода3}]

При выполнении инструкции If проверяется истинность условного выражения условие1.

Замечание

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

Если условие1 имеет значение true, то выполняется блок_кода1, после чего PowerShell завершает выполнение инструкции If. Если условие1 имеет значение false, то PowerShell проверяет истинность условного выражения условие2. Если условие2 имеет значение true, то выполняется блок_кода2, после чего PowerShell завершает выполнение инструкции If. Если и условие1, и условие2 имеют значение false, то выполняется блок_кода3, а затем PowerShell завершает выполнение инструкции If.

Приведем пример использования инструкции If в интерактивном режиме работы. Запишем сначала в переменную $a число 10:

PS C:\> $a=10

Сравним теперь значение переменной $a с числом 15 (в нашем примере используется командлет Write-Host, который выводит информацию на экран):

PS C:\> if ($a -eq 15) {
>> Write-Host '"Значение $a равно 15'
>> }
>> else {Write-Host 'Значение $a не равно 15'}
>>
Значение $a не равно 15

Из данного примера также видно, что в оболочке PowerShell в интерактивном режиме можно выполнять инструкции, состоящие из нескольких строк (это может оказаться очень кстати при отладке сценариев).

Цикл While

В PowerShell поддерживаются несколько видов циклов. Самый простой из них – цикл While, в котором команды выполняются в до тех пор, пока проверяемое условие имеет значение True.

Инструкция While имеет следующий синтаксис:

while (условие){блок_команд}

При выполнении инструкции While оболочка PowerShell вычисляет раздел условие инструкции, прежде чем перейти к разделу блок_команд. Условие в инструкции принимает значения True или False. До тех пор, пока условие имеет значение True, PowerShell повторяет выполнение раздела блок_команд.

Замечание

Как и в инструкции If, в условном выражении цикла While может использоваться конвейер команд PowerShell.

Раздел блок_команд инструкции While содержит одну или несколько команд, которые выполняются каждый раз при входе и повторении цикла.

Например, следующая инструкция While отображает числа от 1 до 3, если переменная $val не была создана, или была создана и инициализирована значением 0.

while($val -ne 3)
{
   $val++
   Write-Host $val
}

В данном примере условие (значение переменной $val не равно 3) имеет значение true, пока $val равно 0, 1 или 2. При каждом повторении цикла значение $val увеличивается на 1 с использованием унарного оператора увеличения значения ++ ( $val++ ). При последнем выполнении цикла значением $val становится 3. При этом проверяемое условие принимает значение false, и цикл завершается.

При интерактивной работе команды удобнее записывать в одной строке, например:

PS C:\> while($val -ne 3){$val++; Write-Host $val}
1
2
3while($val -ne 3){$val++; Write-Host $val}

Обратите внимание, что в качестве разделителя команд в PowerShell используется точка с запятой ( ; ).

Цикл Do … While

Цикл Do…While похож на цикл While, однако условие в нем проверяется не до блока команд, а после:

do{блок_команд}while (условие)

Например:

PS C:\> $val=0
PS C:\> do {$val++; Write-Host $val} while($val -ne 3)
1
2
3
Цикл For

Инструкция For в PowerShell реализует еще один тип циклов – цикл со счетчиком. Обычно цикл For применяется для итерации массива значений и выполнение действий на подмножестве этих значений. В PowerShell инструкция For используется не так часто, как в других языках программирования, так как коллекции объектов обычно удобнее обрабатывать с помощью инструкции Foreach. Однако, если необходимо знать, с каким именно элементом коллекции или массива мы работаем на данной итерации, то цикл For может помочь.

Синтаксис инструкции For:

for (инициация; условие; повторение){блок_команд}

Составные части цикла For имеют следующий смысл:

Классический пример:

PS C:\> for ($i=0; $i -lt 5; $i++) { Write-Host $i }
0
1
2
3
4
Цикл Foreach

Инструкция Foreach позволяет последовательно перебирать элементы коллекций. Самым простым и наиболее часто используемым типом коллекции, по которой производится перемещение, является массив. Обычно в цикле Foreach одна или несколько команд выполняются на каждом элементе массива.

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

Инструкция Foreach вне конвейера команд

В этом случае синтаксис цикла Foreach имеет следующий вид:

foreach ($элемент in $коллекция){блок_команд}

В круглых скобках указывается коллекция, в которой производится итерация. При выполнении цикла Foreach система автоматически создает переменную $элемент. Перед каждой итерацией в цикле этой переменной присваивается значение очередного элемента в коллекции. В разделе блок_команд содержатся команды, выполняемые на каждом элементе коллекции.

Например, цикл Foreach в следующем примере отображает значения в массиве с именем $letterArray:

PS C:\> $letterArray = "a","b","c","d"
PS C:\> foreach ($letter in $letterArray){Write-Host $letter}
a
b
c
d

В первой команде здесь создается массив $letterArray, в который записываются четыре элемента: символы "a", "b", "c" и "d". При первом выполнении инструкции Foreach переменной $letter присваивается значение, равное первому элементу в $letterArray ( "a" ), затем используется командлет Write-Host для отображения переменной $letter. При следующей итерации цикла переменной $letter присваивается значение "b" и т.д. После того, как будут перебраны все элементы массива $letterArray, произойдет выход из цикла.

Инструкция Foreach может также использоваться совместно с командлетами, возвращающими коллекции элементов. Например:

PS C:\> $l = 0; foreach ($f in dir *.txt) { $l += $f.length }
PS C:\> $l
2690555

Здесь сначала создается и обнуляется переменная $l, затем в цикле Foreach с помощью командлета dir формируется коллекция файлов с расширением txt, находящихся в текущем каталоге. В инструкции Foreach перебираются все элементы этой коллекции, на каждом шаге к текущему элементу (соответствующему файлу) можно обратиться с помощью переменной $f. В блоке команд цикла Foreach к текущему значению переменной $l добавляется значение поля length (размер файла) переменной $f. В результате выполнения данного цикла в переменной $l будет храниться суммарный размер файлов в текущем каталоге, которые имеют расширение txt.

Инструкция Foreach внутри конвейера команд

Если инструкция Foreach появляется внутри конвейера команд, то PowerShell использует псевдоним Foreach, соответсвующий командлету Foreach-Object. То есть в этом случае фактически выполняется командлет Foreach-Object и уже не нужно указывать часть инструкции ( $элемент in $коллекция ), так как элементы коллекции блоку команд предоставляет предыдущая команда в конвейере.

Синтаксис инструкции Foreach, применяемой внутри конвейера команд, в простейшем случае выглядит следующим образом:

команда | foreach {блок_команд}

Рассмотренный выше пример с подсчетом суммарного размера текстовых файлов из текущего каталога для данного варианта инструкции Foreach примет следующий вид:

PS C:\> $l = 0; dir *.txt | foreach { $l += $_.length }
PS C:\> $l
2690555

Замечание

Напомним, что специальная переменная $_ используется в командлетах, производящих обработку элементов конвейера, для обращения к текущему объекту конвейера и извлечения его свойств.

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

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

команда | foreach {начальный_блок_команд}
  {средний_блок_команд}{конечный_блок_команд}

Для этого варианта инструкции Foreach наш пример можно записать следующим образом:

PS C:\> dir *.txt | foreach {$l = 0}{ $l += $_.length }{Write-Host $l}
2690555

Запуск сценариев PowerShell

Давайте запустим наш первый сценарий PowerShell. Для этого создадим с помощью Блокнота Windows текстовый файл test.ps1 и запишем в него одну строку:

Write-Host "Эта строка печатается из сценария PowerShell"

Сохраним этот файл в каталоге C:\Script. Как мы помним, сценарии WSH на языках VBScript или JScript можно было запускать из Проводника Windows, щелкая мышью на значках этих сценариев. Со сценариями PowerShell этот метод не работает – если дважды щелкнуть мышью на значке сценария PowerShell, то он не запустится, а откроется для редактирования в Блокноте (это позволяет предотвратить случайный запуск сценария).

Попробуем запустить созданный нами сценарий из оболочки PowerShell:

PS C:\> C:\script\test.ps1

Не удается загрузить файл C:\script\test.ps1, так как выполнение сценариев запрещено для данной системы. Введите "get-help about_signing" для получения дополнительных сведений.

В строка:1 знак:18
+ C:\script\test.ps1 <<<<

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

Для определения того, возможно ли выполнение сценариев на данном компьютере и должны ли эти сценарии быть подписаны цифровой подписью, в оболочке PowerShell используется специальная политика обеспечения безопасности, называемая политикой выполнения.

Политики выполнения сценариев

Политика выполнения (execution policy) оболочки PowerShell определяет, можно ли на данном компьютере выполнять сценарии PowerShell, и если да, должны ли они быть подписаны цифровой подписью. Кроме того, политика выполнения определяет, можно ли загружать конфигурационные файлы при запуске оболочки. Политика выполнения PowerShell хранится в реестре операционной системы и не удаляется даже при переустановке оболочки PowerShell.

Возможные политики выполнения PowerShell описаны в табл. 19.1 (получить аналогичную информацию в PowerShell можно с помощью команды Get-Help about_signing ).

Таблица 19.1. Политики выполнения PowerShell
Название политикиОписание
RestrictedДанная политика выполнения используется по умолчанию, она запрещает выполнение сценариев и загрузку конфигурационных файлов (можно пользоваться только одиночными командами PowerShell в интерактивном режиме)
AllSignedВыполнение сценариев PowerShell разрешено, однако все сценарии (как загруженные из Интернета, так и локальные) должны иметь цифровую подпись надежного издателя. Перед выполнением сценариев надежных издателей запрашивается подтверждение
RemoteSignedВыполнение сценариев PowerShell разрешено, при этом все сценарии и файлы конфигураций, загруженные из Интернета (в том числе по электронной почте и с помощью программ мгновенного обмена сообщениями), должны иметь цифровую подпись надежного издателя, а локальные сценарии могут быть неподписанными. При запуске сценариев надежных издателей подтверждение не запрашивается
UnrestrictedРазрешается выполнение любых сценариев PowerShell без проверки цифровой подписи. При запуске сценариев и файлов конфигураций, загруженных из Интернета, выдается предупреждение

Узнать, какая политика выполнения является активной, можно с помощью командлета Get-ExecutionPolicy:

PS C:\> Get-ExecutionPolicy
Restricted

Командлет Set-ExecutionPolicy позволяет сменить политику выполнения. Например, для установки политики выполнения RemoteSigned нужно выполнить следующую команду:

Set-ExecutionPolicy RemoteSigned

Проверим снова текущую политику:

PS C:\> Get-ExecutionPolicy
RemoteSigned

Теперь вновь попробуем запустить наш сценарий:

PS C:\> C:\script\test.ps1

Эта строка печатается из сценария PowerShell

Как мы видим, сценарий test1.ps1 успешно выполнен.

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

PS C:\> cd script
PS C:\script> dir

    Каталог: Microsoft.PowerShell.Core\FileSystem::C:\script

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        09.12.2007     17:37         59 test.ps1

PS C:\script> test.ps1

Условие "test.ps1" не распознано как командлет, функция, выполняемая программа или файл сценария. Проверьте условие и повторите попытку.

В строка:1 знак:9
+ test.ps1 <<<<

Напомним, что для текущего каталога в системе зарезервировано имя . (точка). Сценарий в текущем каталоге запускается следующим образом:

PS C:\script> .\test.ps1

Эта строка печатается из сценария PowerShell

Для запуска сценария PowerShell непосредственно из командной строки интерпретатора Cmd.exe или с помощью пункта Выполнить (Run) меню Пуск (Start) нужно указать полный путь к этому сценарию после в качестве параметра программы powershell.exe, например:

C:\> powershell.exe C:\script\test.ps1

Дополнения


Литература

  1. Payette B, Windows PowerShell in Action, Manning Publications Co., 2007. – 576 p
  2. Борн Г, Руководство разработчика на Microsoft Windows Script Host 2.0. Мастер-класс, СПб.: Питер; М.: Издательско-торговый дом "Русская редакция", 2001. – 480 с
  3. Попов А.В, Командные файлы и сценарии Windows Script Host, СПб.: БХВ-Петербург, 2002. – 320 с
  4. Попов А.В, Windows Script Host для Windows 2000/XP, СПб.: БХВ-Петербург, 2003. – 640 с
  5. Попов А.В., Шикин Е.А, Администрирование Windows с помощью WMI и WMIC, СПб.: БХВ-Петербург, 2004. – 752 с
  6. Станек У.Р, Командная строка Microsoft Windows. Справочник администратора, М.: Издательско-торговый дом "Русская редакция", 2004. – 480 с
  7. Экк Т, Сценарии ADSI для системного администрирования Windows NT/2000, М.–СПб.–К.: Издательский дом "Вильямс", 2000. – 576 с