...продолжение
- Visual Basic Script
- Зачем нужны VBS-скрипты
- Основные положения
- Переменные
- Ветвления по условию
- Циклы
- Встроенные функции
- Пользовательские функции
- Обработка ошибок выполнения сценария
- Объекты, их методы и свойства
- Методы и свойства корневого класса WScript
- Методы и свойства класса Shell
- Методы и свойства класса Network
- Методы и свойства класса FileSystemObject
- Сценарий "Удаление старых файлов"
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:
- Запустить MS Word.
- В главном меню выбрать Tools -> Macro -> Visual Bacis Editor
- В окне редактирования макросов выбрать View -> Object Browser
Если какая-то библиотека не отражена в списке, то ее можно подключить через меню Tools -> References.
В сценариях есть методы, не входящие ни в какой класс, они доступны непосредственно в теле сценария:
MsgBox(<Message>[, Params]) ' вывод оконного сообщения на экран; InputBox(<Message>[, Params]) ' вывод диалогового окна на экран.
Пример вывода диалогового окна с запросом текста, а после этого вывод на экран оконного сообщения с введенным текстом.
MyValue = InputBox("Введите текст", "Первое окно", "Текст нужно ввести здесь") MyResult = MsgBox(MyValue, 1, "Второе окно")
Методы и свойства корневого класса 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:
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")
Как мы уже убедились, 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 - главный объект, который позволяет создавать, удалять, управлять дисками, папками и файлами в общем;
- 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.