Создание отчетов для данных, полученных из AD

Утилита Csvde, которая после установки системы Windows Server 2003 или Windows 2000 Server находится в каталоге %systemroot%system32, может использоваться для импорта и экспорта данных AD в файлы формата CSV (значения, разделяемые запятой) в соответствии с атрибутами и объектными фильтрами. Например, если требуется извлечь все данные о пользовательском объекте и поместить их в файл с названием C: eport.csv, нужно открыть окно командной строки и ввести следующую команду:

csvde -f c:
eport.csv -v -d 
"dc=mycorp,dc=com"
-r "(objectClass=User)" -p SubTree

Данная команда предписывает Csvde извлечь информацию в указанный файл (параметр –f) и включить подробный режим вывода на экран (параметр –v); указано, что необходимо искать только определенные объекты (т.е. объекты типа «пользователь») (параметр –r), начиная с корня mycorp.com (параметр –d), при этом поиск должен осуществляться в пределах всего дерева (параметр –p). Если нужно извлечь только какое-то определенное свойство пользовательского объекта, скажем ADsPath, тогда дополните команду следующим параметром:

-l ADsPath

Чтобы более подробно изучить синтаксис утилиты Csvde, можно воспользоваться ее параметром "-?" либо запустить csvde вообще без параметров. Кроме того, необходимые сведения можно получить, посетив страницу http://www.microsoft.com/technet/prodtechnol/windowsnetserver/proddocs/entserver/csvde.asp.

После того как данные были извлечены из AD с помощью Csvde, оптимальным способом построения качественного отчета (с форматированными столбцами, заголовками и т.д.) является использование Excel. Например, можно импортировать файл csv в Excel, после чего сохранить отчет в формате Excel (xls). В Листинге 1 показан разработанный мною сценарий VBScript, позволяющий автоматизировать данный процесс, причем Excel здесь открывается без отображения его окна на экране. Данный сценарий создает объект Excel Application, а затем, с помощью метода Workbooks::Open, открывает файл csv, который был ранее сформирован утилитой Csvde (т.е. C: eport.csv). Далее вызывается метод ActiveWorkbook::SaveAs, которому передаются два параметра. Первый из них задает имя вновь создаваемого файла (т.е. C: eport.xls), второй параметр определяет формат (т.е. xlNormal). Следует иметь в виду, что попытка запуска данного сценария на компьютере с Windows 2000 Server, на котором отсутствует Excel, приведет к возникновению ошибки.

Построение отчетов о системе

Если необходимо собрать данные о системе для последующего формирования отчета, рекомендую обратить внимание на Scriptomatic - программный инструмент, позволяющий автоматически создавать сложные сценарии WMI, извлекающие из системы различную информацию. Более подробные сведения о сценариях WMI и других вопросах, связанных с построением отчетов, содержатся в разделе "Список литературы". Данный инструмент распространяется свободно, и его можно загрузить по адресу: http://www.microsoft.com/technet/treeview/default.asp?url=/technet/scriptcenter/wmimatic.asp. На момент написания статьи Microsoft планирует включить данное средство в состав комплекта Windows 2003 resource kit. Scriptomatic может работать на системах Windows 2003, Windows XP и Windows 2000, на Windows NT 4.0 Service Pack 6 (SP6), а также на Windows 98 при наличии установленных компонентов Microsoft Internet Explorer (IE) 5.0, WMI и Windows Script Host (WSH) 5.6. Утилиту Scriptomatic можно использовать для создания базовых сценариев WMI, которые затем можно модифицировать и делать более универсальными.

После того как вы загрузили Scriptomatic, запустите файл scriptomatic.hta. На главном окне вы увидите выпадающий список классов WMI, из которого выбирается нужный. После того как класс был выбран, автоматически генерируется сценарий, с помощью которого можно получить информацию о каждом элементе данного класса на локальной системе. Этот сценарий всегда указывает на локальный компьютер, но его можно соответствующим образом модифицировать и далее запускать на других компьютерах сети. Например, если из списка был выбран класс Win32_OperatingSystem, то Scriptomatic автоматически создает сценарий, который извлекает информацию обо всех элементах данного класса. Если нажать кнопку Run, то Scriptomatic запустит сценарий с помощью сервера сценариев cscript.exe, при этом откроется окно командной строки, в которое будет выведена вся собранная информация. Сценарий можно модифицировать таким образом, чтобы результаты его выполнения экспортировались в Excel.

В Листинге 2 показан пример сценария, созданного Scriptomatic для класса Win32_OperatingSystem, в который было внесено несколько изменений. Прежде всего, для краткости, уменьшен объем собираемых данных, здесь мы ограничиваемся только свойствами CSName, Caption и Version. В Windows XP CSName представляет собой сокращенное имя клиента, Caption - это строка описания, скажем, Microsoft Windows XP Professional, а Version - номер сборки, например, 5.1.2600. Кроме того, сценарий дополнен кодом, который создает объект Excel Application, добавляет к нему книгу (Workbook) и присваивает первому листу книги имя OS Data. Далее в три первые ячейки первой строки (A1, B1 и C1) помещаются названия столбцов (PC Name, Caption и Version). Для выделения заголовков в ячейках этой строки используется темно-синий фоновый цвет, а текст в них отображается белым жирным шрифтом. Код, используемый для автоматизации этих задач в Excel, более подробно рассматривается во врезке "Форматирование отчетов".

Следующие три строки кода взяты непосредственно из Scriptomatic. С их помощью извлекаются данные из класса Win32_OperatingSystem и помещаются в коллекцию под названием colItems. Далее производится заполнение таблицы, путем циклической обработки коллекции, для чего используется маркер индекса строки (обработка начинается со строки 2, т.е. после строки заголовка). В ходе цикла осуществляется запись данных в три столбца, а строковый индекс служит указателем на нужную ячейку. В конце каждого хода цикла маркер индекса строки увеличивается на единицу. Конечно, использование цикла For Each...Next применительно к коллекции colItems, состоящей из одного элемента, может показаться глупостью, однако данный сценарий - это всего лишь пример того, как можно реализовать импорт данных в таблицу Excel. Преимущество сценариев, генерируемых Scriptomatic, заключается в том, что здесь возвращаются все данные по каждому из элементов. В зависимости от выбранного класса WMI количество элементов может быть весьма значительным. Поэтому можно, при необходимости, модифицировать показанный в Листинге 2 сценарий таким образом, чтобы данные по каждому элементу отображались в отдельной строке.

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

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

appExcel.ActiveWorkbook.SaveAs _ 
"C: eport.xls"
appExcel.Workbooks.Close
appExcel.Quit

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

appExcel.Workbooks.Open _ 
"C: eport.xls"
' Perform your changes
appExcel.ActiveWorkbook.Save
appExcel.Workbooks.Close
appExcel.Quit
Remote PCs

Как мы можем модифицировать рассматриваемый сценарий так, чтобы с его помощью можно было собирать информацию об удаленных компьютерах? Ответ содержится в строке strComputer сценария, в которой определяется целевой компьютер. По умолчанию Scriptomatic присваивает этой переменной значение "." (см. фрагмент с меткой A Листинга 2), что соответствует локальной системе. Для того чтобы сценарий выполнялся на удаленном компьютере, нужно просто изменить значение этой переменной, указав вместо "." полное DNS-имя интересующего компьютера, например anotherpc.emea.mycorp.com. А как собрать информацию с нескольких компьютеров? Если этих компьютеров немного, можно включить их имена непосредственно в сценарий, сформировав из них массив, а потом организовать циклическую обработку данного массива. Однако если нужно собрать данные о большом количестве компьютеров – скажем, обо всех компьютерах в заданном организационном подразделении (OU) – тогда необходимо иметь инструмент извлечения их полных DNS-имен из AD. Данное требование опять возвращает нас к уже знакомой утилите Csvde, с помощью которой мы можем экспортировать в файл имена компьютеров, входящих в определенную группу или OU, либо имена всех компьютеров сети.

Допустим, требуется найти все компьютеры, имеющиеся в AD, и получить по каждому из них информацию о свойствах OS Capiton и Version. Это можно сделать с помощью Csvde и модифицированного варианта сценария, сгенерированного Scriptomatic для класса WMI Win32_OperatingSystem. В Листинге 3 показан пример использования Csvde для извлечения списка клиентских компьютеров в файл CSV; затем данный файл открывается с помощью Excel (информация по каждому компьютеру размещается в отдельной строке), после чего производится построчное считывание данных из файла. Далее сценарий пытается подключиться через WMI к каждому из компьютеров и считать информацию об операционной системе. Полученные результаты записываются в другую таблицу Excel, в которой по каждому компьютеру содержатся сведения о том, удалось ли подключиться к нему через WMI, а в случае успешного подключения сюда заносятся необходимые данные по операционной системе соответствующего компьютера.

В начале сценария объявляются нужные переменные и константы. При адаптировании сценария под конкретную рабочую среду потребуется соответствующим образом изменить значения констант PATH, CSV, XLS и AD_ROOT.

Далее с помощью метода WSH Shell::Run запускается утилита Csvde, при этом для окна Run задается скрытый (hidden) режим и устанавливается режим приостановки выполнения сценария до момента завершения работы программы Csvde. Команда запуска Csvde аналогична той, которую мы обсуждали в начале статьи, за исключением того, что здесь установлен фильтр (параметр –r) для поиска компьютеров, а в качестве результатов (параметр –l) будут возвращаться их полные DNS-имена.

После того как будет сформирован файл .csv, сценарий создает объект Excel Application, открывает файл .csv, сохраняет его в виде файла .xls и закрывает исходный файл .csv. Далее вызывается стандартный метод FileSystemObject::DeleteFile, с помощью которого удаляются файлы .csv и csv.log.

Один из листов файла .xls содержит собранную информацию о компьютерах. Данные образуют первый, дополнительный, столбец с отличительными (DN) именами объектов; первая строка также является дополнительной: она представляет собой заголовок, в котором содержатся названия собранных параметров. Поскольку эти данные для нашего отчета не нужны, сценарий удаляет первый столбец и первую строку.

Теперь все требуемые данные находятся в файле .xls на одном рабочем листе с именем Machines (или каким-то другим именем, в зависимости от того, как был назван файл .csv, поскольку Excel открывает файл .csv в одном рабочем листе, которому присваивает то имя, которое носит этот файл). Поскольку имеется только один лист, сценарий может присвоить таблице более информативное имя (скажем, «Информация об операционной системе всех компьютеров»). Для этого нужно просто выбрать все листы и переименовать активный лист. Кроме того, требуется создать строку заголовка, поэтому сценарий вставляет в начало таблицы дополнительную строку, сдвигая остальные ячейки вниз. После этого ячейки пустой строки заполняются заголовками, которые затем форматируются так, как было описано при рассмотрении Листинга 2.

Итак, все готово к заполнению таблицы данными, начиная со строки 2. Чтобы определить, является ли первая ячейка этой строки (т.е. A2) пустой, используется цикл While. Если это не так, иначе говоря, если ячейка содержит имя компьютера, сценарий продолжает выполнение, присваивая переменной strComputer имя, содержащееся в ячейке, после чего пытается собрать по этому компьютеру данные о системе с помощью WMI-кода, сгенерированного Scriptomatic. Перед входом в цикл сценарий проверяет объект objWMIService. Если значение objWMIService равно Nothing, тогда значение счетчика строк увеличивается на единицу, и сценарий переходит к следующей строке. Внутри цикла While после каждого прохода значение objWMIService устанавливается в Nothing. В противном случае, если к удаленному компьютеру не удалось подключиться через WMI, объект не сможет продолжить цикл и перейти к следующей машине в строке.

В ходе циклического перебора коллекции colItems сценарий записывает в первую ячейку текущей строки значение переменной strComputer, а во вторую и третью ячейки – значения Capiton и Version, соответственно. Если при обращении к коллекции colItems возвращается более одного элемента, все последующие строки, содержащие имена остальных компьютеров, к которым мы подключились, сдвигаются вниз, освобождая пространство для этих данных. Здесь же к новым пустым строкам добавляется первая ячейка, содержащая значение переменной strComputer. Таким образом, если, например, коллекция colItems содержит три элемента, сценарий заполняет строку 2 набором данных, соответствующих первому элементу ColItems, создает пустую строку 3, заносит в нее значение strComputer и следующий набор данных из colItems, далее создается пустая строка 4, в которую записываются strComputer и последний набор данных из colItems, после чего создается пустая строка 5. Если в ходе цикла обнаруживается, что коллекция colItems пуста и, соответственно, последнюю пустую строку создавать не нужно, она удаляется. При этом следующая строка, содержащая имя очередного компьютера, перемещается на одну позицию вверх, и сценарий продолжает свое выполнение.

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

Отчеты за одну секунду

Для того чтобы увидеть, как выглядит действительно большой объем данных по каждому компьютеру, отредактируйте сценарий, показанный на Листинге 3 таким образом, чтобы в нем были задействованы класс Win32_Service и свойство Description, и посмотрите, что из этого выйдет. Для проведения такого эксперимента я настоятельно рекомендую ограничить количество компьютеров, к которым вы будете подключаться, поскольку внесенные в сценарий изменения приведут к тому, что по каждому компьютеру для каждой его службы в отчет будет добавляться одна строка, поэтому количество строк по каждому клиенту может превышать 100. Здесь лучше не использовать утилиту Csvde, поэтому закомментируйте строки, обозначенные в Листинге 3 меткой A. Вместо этого используйте готовый файл .csv, в котором должно содержаться не более 10-12 компьютеров. В результате выполнения данного теста вы получите таблицу, содержащую более 1000 строк. Впечатляет, не так ли? Попробуйте поэкспериментировать с Csvde, Scriptomatic и Excel, и скоро создание отчетов по AD и клиентам WMI станет для вас детской забавой.


Форматирование отчетов

Как узнать, какие строки следует добавлять в сценарии VBScript, чтобы можно было автоматизировать работу с Microsoft Excel? Метод очень прост. Открываем Microsoft Excel, выбираем в меню Tools (Сервис), Macro (Макрос), Record New Macro (Начать запись), после чего выполняем те действия, которые хотим автоматизировать в сценарии (например, открытие и сохранение файла, включение автоподбора размеров строк и столбцов, выделение ячеек цветом). Затем останавливаем макрос и открываем для редактирования сгенерированный код VBA (Visual Basic for Applications).

Здесь нужно отметить, что данный код нельзя сразу же использовать в сценариях. Во-первых, такие константы как xlNormal и xlSolid, в VBA уже определены, поэтому для использования этих констант в VBScript сначала нужно найти их значения, а затем объявить их в сценарии. Для этого запустите компонент Object Browser, для чего, находясь в редакторе макросов Microsoft Visual Basic (VB), нажмите клавишу F2 (или выберите из меню редактора View, Object Browser). Выберите в панели Classes класс , после чего, используя полосу прокрутки панели Members of , найдите ту константу, значение которой хотите узнать. После того как константа выбрана, в нижней части окна Object Browser отображается ее содержимое. Во-вторых, в тех случаях, когда процедуры, функции или методы используют параметры, язык VBA является более "многословным" чем VBScript, поэтому код, скорее всего, потребуется редактировать. Рассмотрим приведенный ниже пример, который представляет собой запись последовательности действий при использовании метода SaveAs:

ChDir "C: " 
ActiveWorkbook.SaveAs Filename:= _
"C:Book2.xls", FileFormat:= _
xlNormal, Password:="", _
WriteResPassword:="", _
ReadOnlyRecommended:=False, _
CreateBackup:=False

Из данного макроса видно, что Excel вызывает диалоговое окно Save, из которого мы переходим в корневой каталог диска C:, а затем сохраняем таблицу под именем Book2. Поскольку команда SaveAs включает в себя описание пути, первую строку в данном фрагменте мы удалить не можем. Во второй строке задается шесть параметров; описание каждого из них начинается с имени параметра, за которым следует знак равенства":=". Для того чтобы привести строку к тому виду, в котором ее можно использовать в VBScript, следует удалить из нее названия параметров и знаки равенства "=" и поставить в начале строки префикс "appExcel" (или другой, в зависимости от того, как была названа переменная, которая используется для ссылки на объект Excel Application). Результат будет выглядеть следующим образом:

appExcel.ActiveWorkbook.SaveAs _ 
"C:Book2.xls",xlNormal, _
"", "", False, False

Поскольку в сценарии VBScript мы определили xlNormal как константу, эта строка будет работать. Но нужны ли на самом деле все эти параметры? Для того чтобы выяснить, какие параметры являются обязательными, а какие – нет, вернемся в Object Browser, выберем класс Application (для нашего объекта Excel.Application), после чего выберем пункт ActiveWorkbook (метод, который мы вызываем). При этом в панели результатов видно, что свойство ActiveWorkbook класса Application возвращает объект Workbook, у которого есть метод SaveAs. Следовательно, выбираем в левой панели класс Workbook, а затем в правой выбираем метод SaveAs (данный метод используется в активной книге (active workbook)). В результате в панели будет отображен список параметров метода SaveAs. Если теперь в окне Object Browser щелкнуть мышью на знаке вопроса ("?"),вызывается справка по методу SaveAs. Из данной справки следует, что все параметры метода являются необязательными, что, в принципе, было видно и при просмотре этих параметров в результирующей панели, поскольку все они были заключены в квадратные скобки ("[ ]"). Тем не менее, я все равно рекомендую ознакомиться со справочной информацией, поскольку в ней содержится подробное описание параметров. В данном случае с помощью справочной системы я выяснил, что мне потребуется указать только имя и путь к таблице (т.е. первый параметр). В результате код VBScript будет выглядеть так:

appExcel.ActiveWorkbook.SaveAs "C:Book2.xls"

У кого-то может возникнуть вопрос, почему в данной строке кода не задействован второй параметр, определяющий формат (т.е. xlNormal), аналогично тому, как он использовался в сценарии Листинга 1 основной статьи. Дело в том, что данный параметр задает используемый по умолчанию тип для файла, который вы хотите сохранить. Но в данном случае мы уже работаем с файлом Excel, соответственно, нет необходимости задавать другой тип файла. Что же касается примера из Листинга 4, то там сценарий считывал файл .csv, поэтому, если бы я не задал параметр xlNormal, файл был бы сохранен в том же формате .csv, что мне не требовалось.


Листинг 1. Преобразование файла .csv в файл .xls
Option Explicit
Const xlNormal = &HFFFFEFD1
Dim appExcel
Set appExcel = CreateObject("Excel.Application")
appExcel.Workbooks.Open "C:
eport.csv"
appExcel.ActiveWorkbook.SaveAs "C:
eport.xls", xlNormal
appExcel.Workbooks.Close
appExcel.Quit
Листинг 2. Создание отчета по операционной системе данного компьютера в виде файла .xls
Option Explicit
Const xlSolid = 1
Dim appExcel, strComputer, objWMIService, colItems, objItem, _
        intRowIndex
Set appExcel = CreateObject("Excel.Application")
appExcel.Workbooks.Add
appExcel.Sheets("Sheet1").Name = "OS Data"
appExcel.Sheets("OS Data").Select
appExcel.Cells(1,1).Value="PC Name"
appExcel.Cells(1,2).Value="Caption"
appExcel.Cells(1,3).Value="Version"
 
appExcel.Range("A1:C1").Select
appExcel.Selection.Interior.ColorIndex = 5
appExcel.Selection.Interior.Pattern = xlSolid
appExcel.Selection.Font.ColorIndex = 2
appExcel.Selection.Font.Bold = True
 
# BEGIN CALLOUT A
strComputer = "."
# END CALLOUT A
Set objWMIService = GetObject("winmgmts:" & strComputer & _
        "
ootcimv2")
Set colItems = objWMIService.ExecQuery("Select * from "& _
        "Win32_OperatingSystem",,48)
 
intRowIndex = 2
For Each objItem in colItems
        appExcel.Cells(intRowIndex,1).Value=objItem.CSName
        appExcel.Cells(intRowIndex,2).Value=objItem.Caption
        appExcel.Cells(intRowIndex,3).Value=objItem.Version
        intRowIndex = intRowIndex + 1
Next
 
appExcel.Cells.Select
appExcel.Cells.EntireColumn.AutoFit
appExcel.Cells.EntireRow.AutoFit
 
appExcel.Visible=True
Листинг 3. Код для сбора информации об операционной системе по всем компьютерам
Option Explicit
On Error Resume Next
BEGIN COMMENT LINE
'Объявляем константы и переменные.
END COMMENT LINE
Const FSO_FILE_FORCE_DELETE = TRUE
Const xlNormal = &HFFFFEFD1
Const xlSolid = 1
Const xlShiftDown = &HFFFFEFE7
Const xlShiftUp = &HFFFFEFBE
Const xlToLeft = &HFFFFEFC1
Const SHELL_RUN_HIDE_WINDOW = 0
Const SHELL_RUN_WAIT_UNTIL_FINISHED = TRUE
Const PATH = "C:"
Const CSV = "Machines.csv"
Const CSV_LOG = "CSV.LOG"
Const XLS = "Results.xls"
Const AD_ROOT = "dc=mycorp,dc=com"
Dim wshShell, appExcel, fso, intRowIndex, strComputer
Dim objWMIService, colItems, objItem , strCommand
BEGIN COMMENT LINE
'Используем Csvde для экспорта из AD в файл .csv DNS имен всех клиентских ПК
END COMMENT LINE
# BEGIN CALLOUT A
strCommand = "csvde.exe -f " & PATH & CSV & " -d """ & _
        AD_ROOT & """ -r ""(&(objectClass=Computer))"_
        " -p SubTree -l dNSHostName"
Set wshShell=WScript.CreateObject("WScript.Shell")
wshShell.run strCommand, SHELL_RUN_HIDE_WINDOW, _
        SHELL_RUN_WAIT_UNTIL_FINISHED
# END CALLOUT A
BEGIN COMMENT LINE
'Открываем файл .csv в Excel и сохраняем его в виде файла .xls.
END COMMENT LINE
Set appExcel = CreateObject("Excel.Application")
appExcel.Workbooks.Open PATH & CSV
appExcel.ActiveWorkbook.SaveAs PATH & XLS, xlNormal
BEGIN COMMENT LINE
'Удаляем старый файл .CSV и log-файл.
END COMMENT LINE
Set fso = CreateObject("Scripting.FileSystemObject")
fso.DeleteFile PATH & CSV, FSO_FILE_FORCE_DELETE
fso.DeleteFile PATH & CSV_LOG, FSO_FILE_FORCE_DELETE
BEGIN COMMENT LINE
'Удаляем ненужные первый столбец и первую строку.
END COMMENT LINE
appExcel.Columns("A:A").Select
appExcel.Selection.Delete xlToLeft
appExcel.Rows("1:1").Select
appExcel.Selection.Delete xlShiftUp
BEGIN COMMENT LINE
'Настраиваем таблицу данных об ОС и вставляем в нее строку заголовка.
END COMMENT LINE
appExcel.Worksheets.Select
appExcel.ActiveSheet.Name = "OS Details for All PCs"
appExcel.Rows("1:1").Select
appExcel.Selection.Insert xlShiftDown
BEGIN COMMENT LINE
'Выводим и форматируем заголовки, помещаемые в ячейки первой строки.
END COMMENT LINE
appExcel.Cells(1,1).Value="PC Name"
appExcel.Cells(1,2).Value="Caption"
appExcel.Cells(1,3).Value="Version"
appExcel.Range("A1:C1").Select
appExcel.Selection.Interior.ColorIndex = 5
appExcel.Selection.Interior.Pattern = xlSolid
appExcel.Selection.Font.ColorIndex = 2
appExcel.Selection.Font.Bold = True
BEGIN COMMENT LINE
'Циклическая обработка файла .xls и чтение DNS-имен компьютеров.
END COMMENT LINE
intRowIndex = 2
While appExcel.Cells(intRowIndex,1).Value <> ""
BEGIN COMMENT LINE
        'Пытаемся подключиться к каждому ПК через WMI и фиксируем результаты.
END COMMENT LINE
        strComputer = appExcel.Cells(intRowIndex,1).Value
        Set objWMIService = GetObject("winmgmts:" & strComputer _
                & "
ootcimv2")
        If Not (objWMIService Is Nothing) Then
                Set colItems = objWMIService.ExecQuery("Select * from "& _
                    "Win32_OperatingSystem",,48)
                For Each objItem in colItems
                    appExcel.Cells(intRowIndex,1).Value = strComputer
                    appExcel.Cells(intRowIndex,2).Value = objItem.Caption
                    appExcel.Cells(intRowIndex,3).Value = objItem.Version
                    appExcel.Rows(intRowIndex + 1 & ":" & intRowIndex +1)._
                            Insert xlShiftDown
                    intRowIndex = intRowIndex + 1
                Next
                appExcel.Rows(intRowIndex & ":" & intRowIndex).Delete _
                    xlShiftUp
                Set objWMIService = Nothing
        Else
                intRowIndex = intRowIndex + 1
        End If
BEGIN COMMENT LINE
'Выполняем автоподбор размера ячеек в строках и столбцах, сохраняем файл .xls file
'и переводим Excel в видимый режим.
END COMMENT LINE
appExcel.Cells.Select
appExcel.Cells.EntireColumn.AutoFit
appExcel.Cells.EntireRow.AutoFit
appExcel.ActiveWorkbook.Save
appExcel.Visible = True
ЛИСТИНГ 4. Преобразование файла .csv File в файл .xls
Option Explicit
Const xlNormal = &HFFFFEFD1
Dim appExcel
Set appExcel = CreateObject("Excel.Application")
appExcel.Workbooks.Open "C:
eport.csv"
appExcel.ActiveWorkbook.SaveAs "C:
eport.xls", xlNormal
appExcel.Workbooks.Close
appExcel.Quit