Сценарии для администрирования (Часть 2)

Опубликовано: 24.02.2010
Автор: Виталий Бочкарев
Поддержать автора статьи по этой ссылке

...продолжение

Содержание
Visual Basic Script
Зачем нужны VBS-скрипты

VBS-скрипт - это мощное решение для автоматизации действий пользователя в системах семейства Windows. Такой тип сценариев обычно используется для:

  • создания сложных сценариев;
  • использования объектов из других приложений и библиотек;
  • скрытия окон в ходе выполнения сценария;
  • шифрования логики сценария.

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

Основные положения

В зависимости от языка сценария, содержания и шифрования встречаются такие типы скриптов:

  • vbs - Visual Basic Script
  • vbe - зашифрованный Visual Basic Script
  • js - Java Script
  • jse - зашифрованный Java Script
  • wsh - настройки скрипта
  • wsf - XML-интегрированный сценарий

В этой статье я буду рассматривать сценарии типа vbs.

Сценарии обычно редактируются в блокноте Windows, но я рекомедую использовать Notepad2, который подсвечивает ключевые слова языка Visual Basic и помогает форматировать тело сценария. Итак, vbs-сценарий - это обычный текстовый файл с именем *.VBS, который легко править в блокноте, а запускать на исполнение - двойным щелчком мыши или вызовом по имени в консоли.

Как уже было описано выше, сценарии не компилируются, а интерпретируются. То есть для обработки скрипта в системе должен присутствовать интерпретатор языка VBS, и таких интерпретатора в Windows есть даже две штуки: оконный WScript и консольный CScript - оба интерпритатора - это Windows Script Host (WSH).

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

CScript //H:CScript

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

CScript //H:WScript

В Visual Basic работают следующие правила:

  • длина строки не ограничена;
  • регистр символов не учитывается;
  • количество пробелов между параметрами не учитывается;
  • строку команды можно разрывать, а на месте разрыва нужно вставлять символ " _ ";
  • максимальная длина имени переменной 255 символов;
  • комментарии обозначаются сиволом " ' ".

Рекомендуемая структура сценария:

' === Script Information Header ===
' Script Name:                    ' название сценария;
' Date:                           ' дата изменения;
' Author:                         ' автор;
' Description:                    ' описание;
' === Initialization Block ===
Option Explicit                   ' директива, запрещающая автоматическое создание
                                  ' переменных;
Dim <Variable>                    ' объявление переменных;
Dim <Array>()                     ' объявление массивов;
Set <Object>                      ' подключение объектов;
' === Script Main Logic ===
                                  ' тело сценария;
' === Functions and Procedures ===
                                  ' процедуры и функции;
Примечание. Здесь и далее в треугольных скобках указываются обязательные команды и параметры, значения которых изменяются в зависимости от контекста сценария. В квадратных скобках указываюся необязательные параметры.
Переменные

По умолчанию переменные в сценариях объявляются автоматически при первом использовании в теле скрипта, если это не запрещено директивойOption Explicit. Если же в начале сценария объявить директиву Option Explicit, то все переменные нужно определять заранее с помощью следующих конструкций:

Dim <ValueName1>      ' переменная, доступная всем подпрограммам;
Public <ValueName2>   ' переменная, доступная всем подпрограммам;
Private <ValueName3>  ' переменная, доступная только текущей программе и ее подпрограммам;

Константы объявляются в начале сценария с помощью конструкции:

Const <ConstName1> = <Value1>         ' константа, доступная всем подпрограммам;
Public Const <ConstName2> = <Value2>  ' константа, доступная всем подпрограммам;
Private Const <ConstName3> = <Value3> ' константа, доступная только текущей программе
                                      ' и ее подпрограммам.

Тип переменной присваивается автоматически после внесения в нее первого значения. В Visual Basic существуют следующие типы данных:

  • empty - неинициализированная переменная;
  • null - пустая переменная;
  • boolean - логический тип, возможные значения: False, True или 0, 1;
  • byte - 8-битное целое число без знака, возможные значения: 0 .. 255;
  • integer - 32-битное целое число, возможные значения: -32768 .. 32767;
  • long - 64-битное целое число, возможные значения: -2147483648 .. 2147483647;
  • currency - денежный тип, возможные значения: -922337203685477,5808 до 922337203685477,5807;
  • single - число с плавающей точкой, возможные значения: -3.402823e38 .. -1.401298e-45 для отрицательных чисел и 1.401298e-45 .. 3.402823e38 для положительных чисел;
  • double - число с плавающей точкой, возможные значения: 1.79769313486232e308 .. -4.94065645841247e-324 для отрицательных чисел и 4.94065645841247e-324 .. 1.79769313486232e308 для положительных чисел;
  • date - дата, возможные значения: 01.01.1900 и 31.01.9999;
  • string - строковая переменная, вместимость до 2 миллиардов символов;
  • object - указатель на объект;
  • error - код ошибки.

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

VarType(<Value>)    ' возврат номера типа переменной;
TypeName(<Value>)   ' возврат имени типа переменной;
IsArray(<Value>)    ' проверка, что переменная - это массив;
IsDate(<Value>)     ' проверка, что переменная - это дата;
IsEmpty(<Value>)    ' проверка, что переменная неинициализирована;
IsNull(<Value>)     ' проверка, что переменная пустая;
IsNumeric(<Value>)  ' проверка, что переменная - это число;
IsObject(<Value>)   ' проверка, что переменная - это объект;
CCur(<Value>)       ' конвертация в тип currency;
CBool(<Value>)      ' конвертация переменной в тип boolean;
CByte(<Value>)      ' конвертация переменной в тип byte;
CDate(<Value>)      ' конвертация переменной в тип date;
CDbl(<Value>)       ' конвертация переменной в тип double;
CInt(<Value>)       ' конвертация переменной в тип integer;
CLng(<Value>)       ' конвертация переменной в тип long;
CSng(<Value>)       ' конвертация переменной в тип single;
CStr(<Value>)       ' конвертация переменной в тип string.

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

  • iValueName - числовые типы
  • sValueName - строковый тип
  • bValueName - логический тип
  • dValueName - дата
  • oValueName - объект
  • cValueName - константа
  • aArrayName - массив

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

Dim <ArrayName[(Dimention)]>

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

Dim aMyArray1(10,10)            ' создание статического массива размерностью 11х11;
Dim aMyArray2()                 ' создание динамического массива;
aMyArray1(0,0) = "Hello"        ' заполнение массива;
aMyArray1(0,1) = "People"       ' заполнение массива;
aMyArray1(1,0) = "World"        ' заполнение массива.

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

ReDim aMyArray2(0)            ' формирование массива из одного элемента;
aMyArray2(0) = "Hello"        ' заполнение массива;
ReDim aMyArray2(1)            ' удаление старого массива и формирование нового из
                              ' друх элементов;
aMyArray2(0) = "Hello"        ' заполнение массива;
aMyArray2(1) = "World"        ' заполнение массива;
ReDim Preserve aMyArray2(2)   ' формирование массива из трех элементов, оставляя
                              ' старые значения элементов в тех ячейках, где они были;
aMyArray2(1) = "!"            ' заполнение массива;
Erase aMyArray2               ' удаляление массива.

Чтобы узнать размерность массива, обычно пользуются функцией UBound, которая будет рассмотрена ниже вместе с остальными функциями работы с данными.

Ветвления по условию

Ни один полноценный сценарий не обходится без ветвлений, ветвления помогают выбрать верный путь при выполнении или невыполнении какого-то заложенного условия. Иными словами, ветвления реализуют логику сценария. В VBS-сценариях реализованы несколько механизмов ветвлений. Рассмотрим их по порядку.

Конструкция для одного действия, выполняемого по условию:

If <Condition> Then <Action>

Конструкция для нескольких действий, выполняемых по условию:

If <Condition> Then
   <Action>
   <Action>
End if

Конструкция "развилка":

If <Condition> Then
   <Action>
   <Action>
Else
   <Action>
   <Action>
End if

Конструкция "развилка на несколько путей" (вариант сIf):

If <Condition> Then
   <Action>
   <Action>
ElseIf <Condition> Then
   <Action>
   <Action>
Else
   <Action>
   <Action>
End if

Во всех приведенных выше конструкциях применяется следующее правило: "Если выполняется условие <Condition>, то произвести список действий <Action>, которые расположеные под текущем блоком условия. Если текущее условие не выполняется, то перейти к списку действий <Action> под командой Else."

Конструкция "развилка на несколько путей" (вариант сSelect):

Select Case <Variable>
   Case <Significance>
       <Action>
       <Action>
   Case <Significance>
       <Action>
       <Action>
   Case Else
       <Action>
       <Action>
End Select

В данной конструкции работает правило: "Если значение переменной <Variable> равно значению <Significance>, то произвети список действий <Action> под этим значением, иначе перейти к проверке следующего значения <Significance>."

Циклы

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

Обычный цикл организуется структурой For - Next, в аргументах которой задаются такие параметры как имя счетчика (<Counter>), начальное значение счетчика (<Start>), конечное значение счетчика (<Finish>) и, при необходимости, шаг счетчика (Step <StepSize>).

For <Counter> = <Start> To <Finish> [Step <StepSize>]
   <Actions>
Next

Если в процессе работы цикла потребуется прекратить перебор значений, то это можно сделать с помощью команды Exit For.

For <Counter> = <Start> To <Finish>
   <Actions>
   If <Condition> Then Exit For
   <Actions>
Next

Цикл с неизвестным количеством итераций обычно применяется для перебора всех значений в коллекции объекта, когда не известна его размерность. Эта структура переберет все значения (<Variable>) массива, переданного как парамер цикла (<Array>).

For Each <Variable> In <Array>
   <Actions>
Next

Пример.

For Each oCurrentFile In oFiles
   WScript.Echo oCurrentFile.Name
Next

Циклы с условиями применяются для обработки данных, при выполнении какого-то условия. Такие циклы бывают двух видов: с проверкой в начале цикла и с проверкой в конце.

Цикл, пока выполняется условие, с проверкой в начале

Do While <Condition>
   <Action>
Loop

Цикл, пока не выполнится условие, с проверкой в начале

Do Until <Condition>
   <Action>
Loop

Как уже было сказано выше, условия можно ставить в конец цикла. В этом случае тело цикла будет выполнено как минимум один раз. Так же как и в обычных циклах, цикл с условием можно прервать командой Exit Do:

Do
   <Action>
   If <Condition> Then Exit Do
   <Action>
Loop Until <Condition>
Встроенные функции

Чтобы работать с данными и строить свои процедуры и функции, разработчки Visual Basic уже позаботились об основе сценариев - базовых функциях. VBS-скрипты функции для работы с датами, строками и числами, а так же базовые процедуры ввода-вывода и процедуры работы с сетью. Давайте вкратце рассмотрим встроенные функции.

Функции обработки дат:

Date                                                  ' возврат текущей даты;
Time                                                  ' возврат текущего времени;
Now                                                   ' возврат текущих даты и времени;
DateDiff(<Interval>, <Date1>, <Date2>)                ' возврат разницы между датами;
MonthName(<MonthNumber>)                              ' возврат названия месяца;
WeekDayName(<Day>, <Abbreviation>, <FirstDayOfWeek>)  ' возврат названия дня недели;
Day(<Date>)                                           ' возврат дня из указанной даты;
Month(<Date>)                                         ' возврат месяца из указанной даты;
Year(<Date>)                                          ' возврат года из указанной даты;
Hour(<Date>)                                          ' возврат часа из указанной даты;
Minute(<Date>)                                        ' возврат минуты из указанной даты;
Second(<Date>)                                        ' возврат секунды из указанной даты.

Функции обработки строк:

Asc(<Char>)                                   ' возврат ANSI-кода символа;
Chr(<Number>)                                 ' возврат символа по ANSI-коду;
InStr(<Line>, <Find>)                         ' возврат позиции подстроки в указанной
                                              ' строке;
InStrRev(<Line>, <Find>)                      ' возврат позиции подстроки в указанной
                                              ' строке, начиная с конца строки;
Join(<Array>, <Delimiter>)                    ' преобразование массива в строку;
Len(<Line>)                                   ' возврат длины строки;
LCase(<Line>)                                 ' преобразование строки в строку из малых
                                              ' символов;
UCase(<Line>)                                 ' преобразование строки в строку из больших
                                              ' символов;
Left(<Line>, <Number>)                        ' возврат указанного количества символов с
                                              ' начала строки;
Right(<Line>, <Number>)                       ' возврат указанного количества символов с
                                              ' конца строки;
Mid(<Line>, <StartNumber>, <Number>)          ' возврат указанного количества символов с
                                              ' указанного номера символа строки;
Replace(<Line>, <Find>, <Replace>[, Params])  ' замена подстроки в указанной строке;
Space(<Number>)                               ' строки из указанного количества пробелов;
Split(<Line>, <Delimiter>[, Params])          ' преобразование строки в массив;
String(<Number>, <Char>)                      ' строка из указанного количества
                                              ' определенных символов;
SrtReverse(<Line>)                            ' зеркальное отображение строки;
Trim(<Line>)                                  ' обрезка пробелов слева и справа от строки;
LTrim(<Line>)                                 ' обрезка пробелов слева от строки;
RTrim(<Line>)                                 ' обрезка пробелов справа от строки.

Математические функции:

Randomize         ' инициализация механизма случайных чисел (ничего не возвращает);
Rnd               ' возврат случайного нецелочисленного значения от 0 до 1;
Atn(<Number>)     ' вычисление арктангенса числа;
Cos(<Number>)     ' вычисление косинуса числа;
Sin(<Number>)     ' вычисление синуса числа;
Exp(<Number>)     ' вычисление натурального логарифма числа;
Log(<Number>)     ' вычисление десятичного логарифма числа;
Sqr(<Number>)     ' вычисление квадратного корня числа;
Abs(<Number>)     ' вычисление абсолютного значения числа;
Hex(<Number>)     ' вычисление шеснадцатеричного значения числа;
Int(<Number>)     ' округление числа;
Fix(<Number>)     ' вычисление целой части числа.

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

  • = - оператор присваивания;
  • + - сумма двух чисел;
  • - - вычитание двух чисел;
  • * - умножение двух чисел;
  • / - деление двух чисел;
  • \ - целочисленное деление двух чисел;
  • Mod - остаток от деления двух чисел;
  • ^ - возведение в степень;
  • & - соединение двух строк;
  • Is - сравнение двух объектов;
  • Eqv - сравнение двух выражений;
  • Not - логическая операция отрицания;
  • And - логическая операция конъюнкции;
  • Or - логическая операция дизъюнкции;
  • Xor - логическая операция исключения;
  • Imp - логическая операция импликации.

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

Пользовательские функции

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

Функция объявляется оператором Function, после которого следует название пользовательской функции, которое не должно совпадать ни с одним зарезервированным словом языка Visual Basic, далее указываются переменные, которые будут передаваться подпрограмме в качестве параметров - указание переменных в этой конструкции означает выделение ячеек памяти для переменных подпрограммы (объявление переменных для функции). В теле подпрограммы структура сценария ничем не отличается от обычной программы (здесь можно объявлять дополнительные переменные, поизводить операции, использовать другие функции и процедуры), в конце тела должен присутствовать оператор присвоения функции какому-то значению - это значение и будет возвращено основной программе. Прервать выполнение функции можно оператором Exit Function, но в этом случае нужно не забыть присвоить функции какое-то значение, иначе сценарий выдаст ошибку. Завершается функция оператором End Function.

Определение функции

Function <FunctionName>([Arguments])
   <Actions>
   If <Condition> Then
       <Actions>
       <FunctionName> = <Value>
       Exit Function
   End If
   <Actions>
   <FunctionName> = <Value>
End Function

Вызов функции

<Variable> = <FunctionName>([Arguments])

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

Определение процедуры

Sub <SubName>([arguments])
   <Actions>
   If <Condition> Then
       <Actions>
       Exit Sub
   End If
   <Actions>
End Sub

Вызов процедуры

[Call] <SubName>([arguments])

Кстати, процедуры и функции должны располагаются в конце сценария.

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

Sub <SubName>(ByRef <Argument1>[, arguments])
	   <Actions>
	   <Argument1> = <expression>
	   <Actions>
	End Sub

В данном случае аргумент <Argument1> передается по ссылке на ячейку памяти - меняется значение переменной в основном сценарии. Иными словами, с помощью параметра ByRef процедура превращается в функцию - подпрограмма возвращает результат вычислений в основную программу.

Обработка ошибок выполнения сценария

По умолчанию все ошибки обрабатываются сценарием в автоматическом режиме, и, при возникновении ошибки, работа сценария останавливается. Для отключения автоматической обработки ошибок нужно использовать специальную директиву On Error Resume Next, которая отключает автоматическую обработку ошибок и продолжает работы сценария даже при их наличии. Для ручной обработки ошибок необходимо обратится к встроенному объектуErr, который хранит в себе статус ошибок. Объект Err имеет следующие свойства и методы:

Number          ' возврат номера последней ошибки;
Description     ' возврат описания последней ошибки;
Clear           ' очистка объекта Err;
Raise           ' вызов тестовой ошибки.

Пример ручной обработки ошибки:

On Error Resume Next
iTotalPoints = InputBox("Введите общее количество очков")
iNumberOfTests = InputBox("Введите количество тестов")
iAvarage = iTotalPoints / iNumberOfTests
Select Case Err.Number
   Case 0                            ' нет ошибок;
       WScript.Echo "Средний балл = " & CStr(iAvarage)
   Case 11                           ' деление на ноль;
       WScript.Echo "Количество тестов не может равняться нулю"
   Case 13                           ' несоотвествие типов;
       WScript.Echo "Вы ввели нечисловое значение"
   Case Else                         ' нет ошибок;
       WScript.Echo "Неизвестная ошибка
       WScript.Quit"
End Select
Объекты, их методы и свойства

VBS-сценарии, как и их родитель - язык Visual Basic, является объектно-ориентированным языком программирования, то есть основной концепцией является понятие объектов и классов

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

Итак, чтобы работать с объектом, его нужно сначала создать, используя классы из нужной библиотеки:

Set <ObjectName> = CreateObject(<Library>.<Class>)

Удалить объект можно, присвоив ему значение Nothing:

Set <ObjectName> = Nothing

Все объекты, с которыми работает Windows Script Host, имеют методы и свойства. Чтобы обратиться к методу, необходимо указать объект, а через точку - метод с необходимыми параметрами.

<Object>.<Method> <Param1>[, Param2, ..., ParamN]
Call <Object>.<Method>(<Param1>[, Param2, ..., ParamN])

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

<Object>.<Property> = <Value>
<Object1>.<Property1> = <Object2>.<Property2>
<MyVariable> = <Object>.<Property>

Пример. Создание объекта файловой системы, обращение к методу создания папки, удаление объекта.

Set oFSO = CreateObject("Scripting.FileSystemObject")
Call oFSO.CreateFolder("C:\Test")
Set oFSO = Nothing

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

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

  1. Запустить MS Word.
  2. В главном меню выбрать Tools -> Macro -> Visual Bacis Editor
  3. В окне редактирования макросов выбрать View -> Object Browser

Если какая-то библиотека не отражена в списке, то ее можно подключить через меню Tools -> References.

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

MsgBox(<Message>[, Params])   ' вывод оконного сообщения на экран;
InputBox(<Message>[, Params]) ' вывод диалогового окна на экран.

Пример вывода диалогового окна с запросом текста, а после этого вывод на экран оконного сообщения с введенным текстом.

MyValue = InputBox("Введите текст", "Первое окно", "Текст нужно ввести здесь")
MyResult = MsgBox(MyValue, 1, "Второе окно")
Методы и свойства корневого класса WScript

Методы и свойства корневого класса WScript, не требуют создания объекта - они автоматически доступны для использования непосредственно в теле сценария.

CreateObject(<Library>.<Class>)    ' создание объекта;
GetObject(<FilePath>)              ' подключение объекта из файла;
ConnectObject(<Object>, <Prefix>)  ' подключение к событиям существующего объекта;
DisconnectObject(<Object>)         ' отключение от событий объекта;
Echo([Message])                    ' вывод сообщения на экран;
Arguments                          ' возврат массива аргументов командной строки сценария;
Name                               ' возврат имени интерпретатора сценариев;
Path                               ' возврат пути к интерпретатору сценариев;
FullName                           ' возврат полного имени интерпретатора сценариев;
Version                            ' возврат версии интерпретатора сценариев;
BuildVersion                       ' возврат версии сборки интерпретатора сценариев;
ScriptName                         ' возврат имени файла сценария;
ScriptFullName                     ' возврат полного имени файла сценария;
Interactive                        ' установка или возврат режима интерактивности сценария;
Sleep(<Milliseconds>)              ' приостановка работы на указанное количество миллисекунд;
Quit                               ' прекращение работы сценария.

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

Методы и свойства класса Shell

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

ExpandEnvironmentStrings(<VariableName>) ' возврат значения запрошенной переменной системы;
EnviEnvironment(<VariableName>)          ' возврат массива переменных системы;
CreateShortcut(<PathToCreate>)           ' создание ярлыка;
Popup(<Message>[, Params])               ' вывод оконного сообщения на экран;
RegRead(<ValuePath>)                     ' считывание значения из реестра;
RegWrite(<ValuePath>,<Value>[, Type])    ' запись значения в реестр;
RegDelete(<ValuePath>)                   ' удаление значения из реестра;
LogEvent(<Type>,<Message>)               ' запись события в системный журнал;
Run(<Command>[, Params])                 ' запуск программы в новом процессе;
Exec(<Command>)                          ' запуск программы в дочерней консоли;
AppActivate(<Title>)                     ' активация окна;
SendKeys(<Keys>)                         ' отправка символов в активное окно;
CurrentDirectory                         ' установка или возврат текущей директории;
SpecialFolders([FolderName])             ' возврат массива служебных папок или пути
	                                        ' запрошенной служебной папки.

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

' Создание объекта класса Shell
Set oShell = Wscript.CreateObject("WScript.Shell")
' Запуск калькулятора
oShell.Run("Calc.exe")
' Задержка
WScript.Sleep(100)
' Запуск блокнота
oShell.Run("Notepad.exe")
' Задержка
WScript.Sleep(100)
' Переключение на окно калькулятора
oShell.AppActivate "Calculator"
' Задержка
WScript.Sleep(100)
' Иммитация нажатия клавиш
oShell.SendKeys("1{+}2{=}")
' Получение пути к рабочему столу
sDesktopPath = oShell.SpecialFolders("Desktop")
' Создание объекта ярлыка
Set oLink = oShell.CreateShortcut(sDesktopPath & "\Test.lnk")
' Настрока ярлыка
oLink.TargetPath = WScript.ScriptFullName
oLink.WindowStyle = 1
oLink.Hotkey = "CTRL+SHIFT+T"
oLink.IconLocation = "notepad.exe,0"
oLink.Description = "Test link"
oLink.WorkingDirectory = sDesktopPath
oLink.Save
' Создание объекта среды и получение в него свойств системы
Set oSysEnv = oShell.Environment("SYSTEM")
' Вывод сообщения о количестве процессоров на экран
MyResult = oShell.Popup("Number of processors: " & oSysEnv("NUMBER_OF_PROCESSORS"), _
   3, "Message", 0)
' Получение пути к папке Windows и вывод сообщения на экран
MyResult = oShell.Popup("Windows directory: " & _
   oShell.ExpandEnvironmentStrings("%WINDIR%"), 3, "Message", 0)
' Чтение ключа реестра и вывод его значения на экран
WScript.Echo oShell.RegRead ("HKLM\Software\Microsoft\Windows\CurrentVersion\ProductID")
' Запись строкового значения в реестр
MyResult = oShell.RegWrite("HKCU\ScriptEngine\Value", "My Value")
' Запись числового значения в реестр
MyResult = oShell.RegWrite("HKCU\ScriptEngine\Key", 1, "REG_DWORD")
' Удаление ключа реестра
MyResult = oShell.RegDelete("HKCU\ScriptEngine\")
' Запись события в системный журнал
MyResult = oShell.LogEvent(0, "Test Script Completed")
Методы и свойства класса Network

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

ComputerName                               ' возврат имени компьютера;
UserDomain                                 ' возврат имени домена;
UserName                                   ' возврат имени пользователя;
EnumNetworkDrives                          ' возврат списка подключенных сетевых дисков;
MapNetworkDrive(<LocalName>, <RemoteName>, [UpdateProfile, User, Password])
                                           ' подключение сетевого ресурса;
RemoveNetworkDrive(<Name>, [Force], [UpdateProfile])
                                           ' отключение сетевого ресурса;
EnumPrinterConnections                     ' возврат списка сетевых принтеров;
AddWindowsPrinterConnection(<PrinterPath>) ' подключение сетевого принтера;
AddPrinterConnection(<LocalName>, <RemoteName>[, UpdateProfile, User, Password]
                                           ' подключение сетевого принтера на указанный порт;
RemovePrinterConnection(<Name>[,Force, UpdateProfile])
                                           ' отключение сетевого принтера;
SetDefaultPrinter(<PrinterName>)           ' выбор принтера по умолчанию;

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

' Создание объекта класса Network
Set oNetwork = WScript.CreateObject("WScript.Network")
' Вывод сообщения об имени компьютера
WScript.Echo "Computer Name = " & oNetwork.ComputerName
' Вывод сообщения об имени текущего пользователя
WScript.Echo "User Name = " & oNetwork.UserDomain & "\" & oNetwork.UserName
' Подключение сетевого диска
oNetwork.MapNetworkDrive "Z:" "\\Server\Share"
' Получение коллекции подключенных сетевых дисков
Set oDrives = oNetwork.EnumNetworkDrives
' Вывод сообщений о подключенных сетевых дисках
For i=0 To oDrives.Count -1 step 2
   WScript.Echo "Drive " & oDrives.Item(i) & " = " & oDrives.Item(i+1)
Next
' Удаление сетевого диска
oNetwork.RemoveNetworkDrive "Z:"
' Подключение сетевого принтера
oNetwork.AddPrinterConnection "LPT1", "\\Server\Printer"
' Установка принтера по умолчанию
oNetwork.SetDefaultPrinter "\\Server\Printer"
' Получение коллекции о подключенных принтерах
Set oPrinters = oNetwork.EnumPrinterConnections
Методы и свойства класса FileSystemObject

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

  • FileSystemObject - главный объект, который позволяет создавать, удалять, управлять дисками, папками и файлами в общем;
  • Drive - объект, позволяюший собирать информацию о дисках системы;
  • Drives - объект, хранящий в себе список дисков системы;
  • Folder - объект, позволяющий создавать, удалять, перемещать папки, а также собирать информацию о них и их содержимом;
  • Folders - объект, хранящий в себе список подпапок указанной папки;
  • File - объект, позволяющий создавать, удалять, перемещать файлы, а также собирать информацию о них;
  • Files - объект, хранящий в себе список файлов указанной папки;
  • TextStream - объект, позволяющий читать и создавать текстовые файлы.

Методы и свойства класса FileSystemObject (главного объекта):

BuildPath(<Path>, <Name>)                          ' добавляет имя к указанному пути;
GetAbsolutePathName(<PathSpec>)                    ' возвращает полный путь;
GetBaseName(<Path>)                                ' возвращает имя папки или файла (без
                                                   ' расширения) в указанном пути;
GetDrive(<DriveSpec>)                              ' создает объект Drive;
GetDriveName(<Path>)                               ' возвращает имя диска в указанном пути;
GetExtensionName(<Path>)                           ' возвращает расширение файла в
                                                   ' указанном пути;
GetFile(<FileSpec>)                                ' создает объект File;
GetFileName(<PathSpec>)                            ' возвращает имя файла (без расширения)
                                                   ' в указанном пути;
GetFolder(<FolderSpec>)                            ' создает объект Folder;
GetParentFolderName(<Path>)                        ' возвращает имя папки в котором хранится
                                                   ' файл или папка по указанному пути;
GetSpecialFolder(<FolderSpec>)                     ' создает объект Folder к указанной
                                                   ' служебной папке;
GetTempName                                        ' возвращает случайно сгенерированное
                                                   ' имя файла;
DriveExists(<DriveSpec>)                           ' проверяет существование диска;
FolderExists(<FileSpec>)                           ' проверяет существование папки;
CopyFolder(<Source>, <Destination>[, Overwrite])   ' копирует папку;
MoveFolder(<Source>, <Destination>)                ' перемещает папку;
DeleteFolder(<FolderSpec>[, Force])                ' удаляет папку;
CreateFolder(<FolderName>)                         ' создает папку;
FileExists(<Filespec>)                             ' проверяет существование файла;
CopyFile(<Source>, <Destination>[, Overwrite])     ' копирует файл;
MoveFile(<Source>, <Destination>)                  ' перемещает файл;
DeleteFile(<FileSpec>[, Force])                    ' удаляет файл;
CreateTextFile(<FileName>[, Overwrite, UnioCode])  ' создает текстовый файл;
OpenTextFile(<FileName>[, IOMode, Create, Format]) ' открывает текстовый файл для чтения или
                                                   ' записи.

Объекты Drives, Folders и Files класса FileSystemObject хранят в себе информацию о дисках, папках и файлах и, в основном, используюся для сбора информации о файловой системе. Они имеют только два свойства:

Count                ' возвращает количество элементов в коллекции;
Item(<ObjectName>)   ' возвращает запись с указанным индексом из коллекции (не используется),
                     ' для перебора элементов коллекции приметяется цикл For Each.

Чтобы было более понятно, что же такое коллекция объектов, рассмотрим пример вывода на экран списка файлов корня диска C:

' Создание объекта класса FileSystemObject
Set oFSO = CreateObject("Scripting.FileSystemObject")
' Создание объекта Folder
Set oFolder = oFSO.GetFolder("C:\")
' Получение коллекции файлов
Set oFilesCollection = oFolder.Files
' Получение количества элементов в коллекции
sResult = sResult & oFilesCollection.Count & " files in C:\" & vbCrLf
' Чтение атрибутов каждого файла из коллекции
For Each oFile in oFilesCollection
   sResult = sResult & oFile.Name & vbTab
   sResult = sResult & oFile.Size & vbCrLf
Next
' Вывод результата на экран
MsgBox(sResult)

Объект Drive предоставляет доступ к свойствам локального или сетевого диска:

AvailableSpace   ' возвращает размер свободного места на диске, доступного пользователю;
DriveLetter      ' возвращает букву диска;
DriveType        ' возвращает тип диска;
FileSystem       ' возвращает тип файловой системы диска;
FreeSpace        ' возвращает размер свободного места на диске;
IsReady          ' возвращает доступность диска;
Path             ' возвращает путь к диску;
RootFolder       ' создает объект Folder, указывающий на корень диска;
SerialNumber     ' возвращает серийный номер диска;
ShareName        ' возвращает сетевое имя диска;
TotalSize        ' возвращает емкость диска в байтах;
VolumeName       ' возвращает или устанавливает метку диска.

Объект Folder предоставляет доступ ко всем свойствам папки, а также позволяет производить над ней действия:

Attributes                         ' возвращает атрибуты папки;
DateCreated                        ' возвращает дату создания папки;
DateLastAccessed                   ' возвращает дату последнего доступа к папке;
DateLastModified                   ' возвращает дату изменения папки;
Drive                              ' возвращает букву диска, на котором расположена папка;
Files                              ' возвращает коллекцию файлов папки;
IsRootFolder                       ' возвращает True, если папка - это корень диска;
Name                               ' возвращает имя папки;
ParentFolder                       ' создает объект Folder, указывающий на
                                   ' родительскую папку;
Path                               ' возвращает путь к папке;
ShortName                          ' возвращает имя папки в формате 8.3;
ShortPath                          ' возвращает путь к папке в формате 8.3;
Size                               ' возвращает размер папки;
SubFolders                         ' возвращает коллекцию подпапок;
Type                               ' возвращает тип папки;
Copy(<Destination>[, Overwrite])   ' копирует папку;
Move(<Destination>)                ' перемещает папку;
Delete(<Force>)                    ' удаляет папку;
CreateTextFile(<FileName>[, Overwrite, UniCode])
                                   ' создает в папке текстовый файл.

Объект File аналогичен объекту Folder - он предоставляет доступ ко всем свойствам файла, а также позволяет производить над ним действия:

Attributes                           ' возвращает атрибуты файла;
DateCreated                          ' возвращает дату создания файла;
DateLastAccessed                     ' возвращает дату последнего доступа к файла;
DateLastModified                     ' возвращает дату изменения файла;
Drive                                ' возвращает букву диска, на котором расположен файл;
Name                                 ' возвращает имя файла;
ParentFolder                         ' создает объект Folder, указывающий на
                                     ' родительскую папку;
Path                                 ' возвращает путь к файлу;
ShortName                            ' возвращает имя файла в формате 8.3;
ShortPath                            ' возвращает путь к файлу в формате 8.3;
Size                                 ' возвращает размер файла;
Type                                 ' возвращает тип файла;
Copy(<Destination>[, Overwrite])     ' копирует файл;
Move(<Destination>)                  ' перемещает файл;
Delete(<Force>)                      ' удаляет файл;
OpenAsTextStream([IOMode, Format])   ' открывает текстовый файл для чтения или записи.

Объект TextStream - это инструмент доступа к содержимому файла. С помощью него можно читать и изменять файл:

AtEndOfLine                ' показывает, достигнут ли конец строки;
AtEndOfStream              ' показывает, достигнут ли конец строки;
Column                     ' возвращает номер колонки, в которой находится курсор чтения;
Line                       ' возвращает номер строки, в которой находится курсор чтения;
Close                      ' закрывает файл - освобождает его для других процессов;
Read(<CharactersNumber>)   ' считывает указанное количество символов, начиная от позиции
                           ' курсора чтения;
ReadAll                    ' считывает весь файл;
ReadLine                   ' считывает строку, в которой находится курсор чтения;
Skip(<CharactersNumber>)   ' пропускает указанное количество символов, начиная от позиции
                           ' курсора чтения;
SkipLine                   ' пропускает строку, в которой находится курсор чтения;
Write(<String>)            ' записывает строку;
WriteLine(<String>)        ' записывает строку и переводит курсор записи на следующую строку;
WriteBlankLines(<Lines>)   ' записывает указанное количество пустых строк.

Мы познакомились со всеми методами и свойствами класса FileSystemObject, рассмотрим пример использования этого класса:

' Задание констант кодов системных папок
Const WindowsFolder = 0
Const SystemFolder = 1
Const TemporaryFolder = 2
' Задание констант кодов типов доступа к текстовому файлу
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
' Создание объекта класса FileSystemObject
Set oFSO = CreateObject("Scripting.FileSystemObject")
' Получение коллекции дисков
Set DrivesCollection = oFSO.Drives
' Обработка каждого диска для получения его метки или сетевого имени
For Each oDrive in DrivesCollection
   sResult = sResult & oDrive.DriveLetter & ": "
   If oDrive.DriveType = Remote Then
       sResult = sResult & oDrive.ShareName & vbCrLf
   ElseIf oDrive.IsReady Then
       sResult = sResult & oDrive.VolumeName & vbCrLf
   Else
       sResult = sResult & vbCrLf
   End If
Next
' Вывод результатов на экран
Wscript.Echo(sResult)
' Создание объекта диска C:
Set oDrive = oFSO.GetDrive("C")
sResult = oDrive.DriveLetter & ": - "
' Получение типа диска C:
Select Case oDrive.DriveType
   Case 0: sResult = sResult & "Unknown - "
   Case 1: sResult = sResult & "Removable - "
   Case 2: sResult = sResult & "Fixed - "
   Case 3: sResult = sResult & "Network - "
   Case 4: sResult = sResult & "CD-ROM - "
   Case 5: sResult = sResult & "RAM Disk - "
End Select
' Определение доступности диска и получение его свойств
If oDrive.IsReady Then
   sResult = sResult & "Ready" & vbCrLf
   sResult = sResult & "FileSystem is " & oDrive.FileSystem & vbCrLf
   sResult = sResult & "Available Space: " & _
     FormatNumber(oDrive.AvailableSpace/1024, 0) & " Kbytes"
Else
   sResult = sResult & "Not ready"
End If
' Вывод результатов на экран
Wscript.Echo(sResult)
' Создание объекта служебной папки (папка временных фалов Windows)
Set oTempFolder = oFSO.GetSpecialFolder(TemporaryFolder)
' Создание объекта текстового файла (и создание его в корне диска C:)
Set oFile = oFSO.CreateTextFile("C:\TestFile.txt", True)
' Запись в текстовый файл
oFile.WriteLine("This is a test.")
oFile.WriteLine(sResult)
' Закрытие текстового файла и освобождение его для других процессов
oFile.Close
' Проверка на наличие файла в папке временных файлов Windows, удаление этого файла
If oFSO.FileExists(oFSo.BuildPath(oTempFolder.Path, "TestFile.txt")) Then _
 oFSO.DeleteFile(oFSo.BuildPath(oTempFolder.Path, "TestFile.txt"))
'  Создание объекта файла
Set oFile = oFSO.GetFile("C:\TestFile.txt")
' Перемещение файла в папку временных файлов Windows
oFile.Move(oFSo.BuildPath(oTempFolder.Path, "TestFile.txt"))
' Изменение атрибута у файла
If oFile.Attributes and 32 Then
   oFile.Attributes = oFile.attributes - 32
   Wscript.Echo("Archive bit is cleared")
Else
   oFile.Attributes = oFile.attributes + 32
   Wscript.Echo("Archive bit is set")
End If
sResult = oFile.Path & vbCrLf & oFile.DateLastModified & ":" & vbCrLf
' Создание объекта потока путем открытие файла на чтение
Set oTestFile = oFSO.OpenTextFile(oFile.Path, ForReading, False)
' Чтение потока, пока не встречен его конец
Do While oTestFile.AtEndOfStream <> True
   sResult = sResult & oTestFile.ReadLine
Loop
' Закрытие текстового файла и освобождение его для других процессов
oTestFile.Close
' Вывод сообщения на экран
Wscript.Echo(sResult)
Сценарий "Удаление старых файлов"

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

' ==== Script Information Header ====
' script name:   Purge Temp
' version:       1.0
' date:          16.07.08
' autor:         Bochkarev Vitaly
' description:   Скрипт удаляет устаревшие временные файлы с компьютера

' ==== Script Main Logic ====
' Включение ручной обработки ошибок
On Error Resume Next
' Константа временного интервала, когда файлы считаются устаревшими
Const PurgeTime = 14    ' дней

' Исключения - профили пользователей, которые не должны обрабатываться
Dim aExceptions(3)
aExceptions(0) = "Default User"
aExceptions(1) = "LocalService"
aExceptions(2) = "NetworkService"
aExceptions(3) = "All Users"

' Создание объектов оболочки и файловой системы
Set oShell = CreateObject("wscript.shell")
Set oFSO = CreateObject("Scripting.Filesystemobject")

' Определение путей служебных папок
sProgramFiles = oShell.ExpandEnvironmentStrings("%ProgramFiles%")
sWinDir = oShell.ExpandEnvironmentStrings("%WinDir%")
sWinTempFolder = sWinDir & "\Temp"
sDocuments = "C:\Documents and Settings"

' Создание фурнала работы сценария
sLogFileName = sWinTempFolder & "\PurgeTemp_" & Date
sLogFileName = Replace(sLogFileName, ".", "_")
sLogFileName = Replace(sLogFileName, "/", "_")
Set oLogFile = oFSO.CreateTextFile(sLogFileName & ".log",true)
oLogFile.WriteLine "========== Start purging =========="

' Очистка временной папки Windows
oLogFile.WriteLine vbCrLf & "========== Windows Temporary folder =========="
PurgeFolder(sWinTempFolder)

' Очистка временной папки профиля пользователя и файлов Интернет
oLogFile.WriteLine vbCrLf & _
 "========== Users Temporary folder and Users Temporary Internet Files =========="
Set oDocuments = oFSO.GetFolder(sDocuments)
Set colProfiles = oDocuments.SubFolders
For Each oProfile In colProfiles
   bFlag = false
   For Each sException in aExceptions
       if InStr(oProfile.Path,sException) > 0 then
           bFlag = true
           exit for
       end if
   Next
   If bFlag = False Then
       PurgeFolder(oProfile.Path & "\Local Settings\Temp")
       PurgeFolder(oProfile.Path & "\Local Settings\Temporary Internet Files")
   End If
Next

' Очистка карантина NOD32
oLogFile.WriteLine vbCrLf & "========== NOD32 Quarantine =========="
sQuarantine = sProgramFiles & "\Eset\Infected"
PurgeFolder(sQuarantine)

' Закрытие файла журнала
oLogFile.WriteLine vbCrLf & "========== Stop purging =========="
oLogFile.Close

' Процедура PurgeFolder - удаление старых файлов
Sub PurgeFolder(sFolderPath)
   ' Создание объекта Folder
   Set oFolder = oFSO.GetFolder(sFolderPath)
   ' Получение коллекции файлов
   Set colFiles = oFolder.Files
   ' Обработка каждого файла из коллекции
   For each oFile in colFiles
       ' Проверка, является ли файл устаревшим
       If (Date-oFile.DateLastModified) > PurgeTime and (Date-oFile.DateCreated) > _
         PurgeTime Then
           ' Запись сообщения в журнал сценария
           oLogFile.Writeline oFile.Path & vbTab & oFile.DateCreated
           ' Удаление устаревшего файла
           oFSO.DeleteFile oFile.Path, True
           ' Проверка на наличие ошибок
           if err.Number <> 0 then
               ' Запись сообщения об ошибке в журнал сценария
               oLogFile.Writeline "-----> Error # " & CStr(Err.Number) _
                 & " " & Err.Description
               ' Очистка ошибки
               Err.Clear
           end if
           ' Пауза в 20 милисекунд
           WScript.Sleep 20
       End if
   Next
   ' Получение коллекции подпапок
   Set colSubFolders = oFolder.SubFolders
   ' Обработка каждой подпапки
   For Each oSubFolder In colSubFolders
       ' Рекурсивный вызов процедуры удаления старых файлов - подпрограмма вызывает
       ' сама себя
       PurgeFolder(oSubFolder.Path)
       ' Проверка размера папки
       If oSubFolder.Size = 0 Then
           ' Запись сообщения в журнал сценария
           oLogFile.Writeline oSubFolder.Path & vbTab & oSubFolder.DateCreated
           ' Удаление пустой папки
           oFSO.DeleteFolder oSubFolder.Path
           ' Проверка на наличие ошибок
           If err.Number <> 0 then
               ' Запись сообщения об ошибке в журнал сценария
               oLogFile.Writeline "-----> Error # " & CStr(Err.Number) _
                 & " " & Err.Description
               ' Очистка ошибки
               Err.Clear
           End if
       End if
   Next
End Sub

 

Итак, мы познакомились с основами сценариев Visual Basic Script. Давайте подведем итог, и определим достоинства и недостатки таких сценариев:

  • сценарии не требуют компиляции и их код в любой момент можно отредактировать;
  • VBS-сценарии практически не ограничены в функциональности и могут использовать различные системные библиотеки и объекты других приложений;
  • VBS-файлы могут выполняются как в консоли, так и в оконном режиме, поэтому пользователь может контролировать видимость хода выполнения сценария;
  • VBS-сценарии позволяют использовать пользовательские процедуры и функции;
  • этот язык идеально подходит для работы со строковыми и числовыми переменными, датами, а также для обработки текстовых файлов, управления системой и доменом;
  • VBS-сценарии сложны в написании и требуют навыков программирования;
  • такие сценарии работают только в операционных системах семейства Windows.
Инструменты для написания скриптов ScriptReference.zip
Виталий Бочкарев