Должен признаться, что за те годы, что я занимался составлением сценариев, они «заполонили» все уголки моего компьютера. Сценарии обитают у меня в большом числе папок на различных накопителях. Некоторые из них хорошо организованы, некоторые — нет. Об одних сценариях я забыл, другие в течение весьма длительного времени прятались в неприметных местах.

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

Так вот, вместо того чтобы «вылавливать» свои сценарии и копировать их на накопитель USB или резервируемый сетевой ресурс, я решил собрать их все с помощью специального сценария.

С помощью средств управления Windows Management Instrumentation (WMI) сценарий ScriptRoundUp.vbs (см. листинг) находит файлы .vbs и .hta, записанные на локальных накопителях  C и D. Запрос, используемый в сценарии, можно с легкостью модифицировать так, чтобы он проверял другие локальные накопители и отыскивал файлы с другими расширениями; в результате, внеся в код лишь самое незначительное изменение, пользователи могли бы собирать сценарии Windows PowerShell, документы Windows Word или электронные таблицы Excel.

Как использовать сценарий

О возможности обнаружения файлов средствами WMI известно многим из тех, кто занимается сценариями. Так чем же код ScriptRoundUp.vbs отличается от множества сценариев на базе WMI, которые, возможно, уже написаны? Основное отличие состоит в следующем. ScriptRoundUp.vbs снимает копии всех файлов, соответствующих заданным критериям, и размещает их в централизованном каталоге так, чтобы все сценарии находились в одном месте. Затем можно, что называется, одним махом скопировать их из централизованного каталога на накопитель USB или на сетевой ресурс. Этот централизованный каталог жестко закодирован в сценарии как C:ScriptsAllScriptsScriptFiles. Сценарий не создает эту папку, поэтому нужно будет создать ее перед тем, как запускать сценарий.

Если вы хотите хранить эти копии в другой папке, потребуется найти фрагмент

ColPath = "C:ScriptsAllScripts"
DestRoot = ColPath & "ScriptFiles"

в начале сценария ScriptRoundUp.vbs. ColPath — это путь к коллекции, где сценарий создает и хранит базу данных .xml, содержащую сведения обо всех файлах, возвращенных при выполнении запроса WMI. В данном случае базу данных .xml содержит папка C:ScriptsAllScripts. Переменная DestRoot указывает на корневую папку-получатель, в которой будут храниться все сценарии; конкретно речь идет о папке ScriptFiles. Вместо данной вложенной папки можно указать другую; для этого требуется изменить вторую строку. Но будьте внимательны — имена переменных ColPath и DestRoot должны при этом оставаться неизменными. Еще раз напоминаю: вложенную папку следует создавать до того, как будет запускаться сценарий.

Файлы VBScript и приложения HTML (HTML Applications, HTA) обычно не занимают много места. У меня хранится более тысячи сценариев и приложений HTA, и в сумме они занимают всего лишь 56 Мбайт. Однако, если на вашем диске C отмечается явный недостаток свободного пространства, пожалуй, более целесообразно будет в переменной ColPath указать путь к иной папке на другом накопителе.

Кроме того, имеется лишь один фрагмент кода, который вы, возможно, захотите модифицировать; это запрос WMI

strQuery = «Select Drive, Name,
Extension, Path from
CIM_DataFile " & _
"Where (Drive='c:' OR Drive='d:')
AND (extension='vbs' OR
extension='hta')"

Данный запрос предписывает искать файлы VBScript и HTA на дисках C и D. Данный фрагмент можно с легкостью модифицировать таким образом, чтобы обнаруживать другие типы файлов на других накопителях. Так, если вам нужны файлы JScript и PowerShell, видоизмененная инструкция должна выглядеть так:

strQuery = «Select Drive, Name,
Extension, Path from CIM_DataFile
" & _
"Where (Drive='c:' OR Drive='d:')
AND (extension='js' OR
extension='ps1')"

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

Рекомендую перед вторым запуском сценария ScriptRoundUp.vbs удалить все файлы и папки из папки C:ScriptsAllScripts (после того, как вы скопируете их в безопасное место). Если они останутся на жестком диске и сценарий будет запущен вторично, эти файлы также будут собраны, что фактически удвоит время, необходимое для выполнения сценария, а также вдвое увеличит пространство, необходимое для хранения файлов.

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

Как работает сценарий

Как показано в листинге, файл ScriptRoundUp.vbs довольно компактен и не слишком сложен. Рассмотрим, как он работает.

Создав ссылочные переменные и строку запроса, сценарий проверяет накопитель на наличие обеих папок — C:ScriptsAllScripts и C:ScriptsAllScriptsScriptFiles. Если найти такие папки не удается, на экране появляется сообщение, извещающее пользователя о том, что одна или обе папки отсутствуют, и выполнение сценария прекращается. Далее во фрагменте A листинга сценарий создает объект Folder с именем RootFolder, привязанный к корневой папке-получателю. Этот объект является частью интерфейса Windows Shell API для сценариев. С помощью метода NewFolder объекта Folder сценарий может добавлять в корневую папку-получатель вложенные папки. Имена вложенных папок образуются из реальных имен папок, в которых находятся файлы .vbs и .hta.

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

  • поле Drive, содержащее буквенное обозначение накопителя с файлом (например, C);
  • поле Extension, содержащее расширение имени файла (например, .vbs);
  • поле Name, содержащее полный путь к файлу и его имя (например, C:ScriptsRoundUpScript Roundup.vbs);
  • поле Path, содержащее только путь с открывающими и завершающими символами обратной косой черты (например, ScriptsRoundUp).

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

Во фрагменте C сценарий выполняет запрос WMI и сохраняет в коллекции отвечающие заданным критериям файлы. С помощью инструкции For Each… Next языка VBScript сценарий «прочесывает» всю коллекцию. Значения накопителя, расширения имени и пути, относящиеся к каждому файлу, считываются и заносятся в соответствующие поля базы данных. После того как все данные о файле занесены в базу данных, указатель записи располагается у первой записи.

Инструкция Do… Loop во фрагменте D — это настоящее «сердце» сценария. Именно с ее помощью создаются все вложенные папки и копируются все файлы. Не упускайте из виду, что все вложенные папки создаются в корневой папке-получателе. Так, файл C:ScriptsRoundUp ScriptRoundup.vbs будет копироваться в папку C:ScriptsAllScripts ScriptFilesCScriptsRoundUp ScriptRoundup.vbs.

Давайте подробнее остановимся на инструкции Do… Loop. Первая строка

FolderPath = Replace (DRS. Fields.Item
("Drive"),":","") & DRS. Fields.Item
("Path")

задает значение переменной FolderPath на базе буквенного обозначения накопителя (с удаленным символом двоеточия) и пути. Результирующее значение будет выглядеть примерно так: CScriptsRoundUp. Для создания вложенной папки, в которой разместится файл, будет использоваться переменная FolderPath. Однако прежде сценарий проверит переменную FolderPath на наличие вложенной папки. И если папка уже существует, сценарий не будет предпринимать попыток вновь создавать ее. Строка

Dest = DestRoot & "" & Replace
(DRS. Fields.Item ("Drive"),":","")
& DRS. Fields.Item ("Path")

формирует переменную Dest, которая используется для проверки наличия папок. Значение переменной Dest формируется таким же образом, как и значение переменной FolderPath, с тем лишь исключением, что перед значением Dest указывается значение DestRoot (C:ScriptsAllScripts ScriptFiles), и в результате формируемая переменная выглядит приблизительно так: C:Scripts AllScriptsScriptFilesCScripts RoundUp.

После создания переменной Dest производится проверка ее существования с помощью следующего кода

If Not fso.FolderExists (Dest) Then
RootFolder.NewFolder (FolderPath)
End If

Если искомая вложенная папка не существует, инструкция RootFolder.NewFolder (FolderPath) использует имя, хранимое в переменной FolderPath для создания этой вложенной папки внутри корневой папки-получателя.

Далее, строки

Set sourcefile = nothing
Set sourcefile = fso.getFile
(DRS.Fields.Item ("Name"))
sourcefile.Copy Dest

разрывают ассоциацию переменной sourcefile с любым объектом, а затем ассоциируют эту переменную с объектом Scripting Runtime Library File; последний связан с файлом, ассоциированным со значением, которое хранится в поле Name базы данных. Напомню, что поле Name содержит полный путь к файлу, первоначально возвращенному запросом WMI, а также имя этого файла. Поскольку объект File уже создан, остается только вызвать метод Copy данного объекта, с тем чтобы скопировать заданный в переменной Name файл .vbs или .hta во вложенную папку, указанную в переменной Dest. Этот процесс повторяется для каждой записи базы данных до тех пор, пока не будет достигнут конец файла; после этого база данных сохраняется под именем C:ScriptsAllScriptsScripts.xml. Вот и все, остается только скопировать собранные файлы в выбранную папку. Не забудьте только удалить их из области коллекции, если собираетесь вновь запускать сценарий с использованием тех же критериев.

Джим Тернер (jturnervbs@gmail.com) — системный администратор и разработчик приложений в компании Computer Sciences Corporation


Листинг. ScriptRoundUp.vbs