Аудит установленного программного обеспечения обычно выполняется администратором для проверки соблюдения лицензионных соглашений, выявления наличия нелегальных программных средств, а также при подготовке к обновлению версии или миграции. Для этих целей можно устанавливать различные утилиты от независимых фирм и агенты, которые могут не только осуществлять инвентаризацию программного обеспечения, но и собирать сведения о свободном дисковом пространстве, статусе служб, версии BIOS, а также распространять программное обеспечение на клиентские системы. Тем не менее во многих случаях бывает достаточно только сведений о программах, установленных на сервере или рабочей станции. Оснастка «Установка и удаление программ» в панели управления обращается для этих целей к одному из разделов реестра и значениям его параметров. Соответственно и мы можем обратиться к этой же ветви и получить из нее список установленных программ. В листинге показан сценарий QueryInstalledSoftware.cmd, с помощью которого можно легко и быстро выполнить данную процедуру, получив таким образом недорогой инструмент для проведения аудита программного обеспечения.

Использование программы Reg.exe для обращения к реестру

Данные об установленных программах, которые использует оснастка «Установка и удаление программ», хранятся в реестре в разделе HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionUninstall. Для удаленного обращения к реестру можно воспользоваться утилитой Reg.exe (которая раньше была в составе Microsoft Windows NT 4.0 Resource Kit, а теперь включена в пакет Windows 2000 Support Tools и более поздних  версий). С помощью Reg.exe можно создавать, удалять и модифицировать параметры реестра из командной строки. Раздел Uninstall содержит параметры, описывающие установленные в системе приложения, такие как имя, источник установки и строка удаления (uninstall string) программы. Параметр displayname представляет собой имя программы в том виде, в котором оно отображается в оснастке «Установка и удаление программ». Для обращения к данному разделу реестра с помощью Reg.exe можно воспользоваться следующей командой:

Reg Query HKLMSOFTWARE
MicrosoftWindows   CurrentVersionUninstall
 /S
compname

В тексте статьи данная команда выглядит как несколько строк, но при ее запуске из командной строки она должна набираться одной строкой. Сказанное относится и ко всем остальным многострочным командам, описанным в статье. В результате выполнения данной команды будут выведены значения всех параметров раздела Uninstall для компьютера, имя которого определяется параметром compname. Поскольку вся эта информация нам не требуется, ограничим вывод только значениями параметров displayname. Проще всего это можно сделать, перенаправив вывод данных, полученных от команды Reg Query, на вход команды Find:

Reg Query HKLMSOFTWARE 
MicrosoftWindows   CurrentVersionUninstall 
/S
compname | Find /I
«displayname»

Такая организация вывода существенно лучше, чем вывод «сырых» данных, получаемых в результате выполнения команды Reg Query, однако здесь также будут отображаться значения параметров quietdisplayname. В оснастке «Установка и удаление программ» скрытые имена не отображаются, поскольку они представляют собой либо промежуточные  программы, либо зависимые  модули других программ. Поскольку в большинстве случаев эти данные нас не интересуют, еще раз перенаправим вывод в команду Find, на этот раз используя вместе с параметром quietdisplayname ключи /V и /I:

Reg Query HKLMSOFTWARE   MicrosoftWindows   CurrentVersionUninstall
/S
compname | Find /I
«displayname» | Find /V /I
«quietdisplayname»

Применение этой команды позволит полностью исключить из выходных данных строки, содержащие quietdisplayname. Внешний вид данных, выводимых этой командой, показан на экране.
Разумеется, для того чтобы получить нужный результат, можно непосредственно воспользоваться описанной выше командой, однако в данном случае предпочтительно применение сценария. Это обусловлено двумя причинами. Во-первых, сама по себе данная команда является достаточно длинной и каждый раз полностью набирать ее в командной строке — занятие довольно утомительное. А во-вторых, при использовании сценария есть возможность манипулировать выходными данными так, чтобы на экране отображались только имена. Иначе говоря, можно отфильтровать из выходных данных значения «REG_SZ» и «DisplayName».
Для запуска сценария используется следующий командный синтаксис:

QueryInstalledSoftware.cmd
computername

где computername — имя компьютера, к которому мы обращаемся. Поскольку имя компьютера используется в сценарии неоднократно, это значение заносится в переменную targetcomp, что облегчает понимание текста сценария. Чтобы сократить время ожидания, сценарий с помощью команды Nbtstat сразу же проверяет доступность заданного компьютера по сети. Если подключиться к нужному компьютеру нельзя, сценарий уведомляет об этом пользователя и сразу же завершает свою работу.
Далее запускается команда Reg Query. Для того чтобы структурировать данные в виде столбцов, удобно воспользоваться командой For. Если посмотреть на результаты вывода команды, показанные на экране, видно, что здесь имеется три столбца, причем имя приложения отображается в третьем. По умолчанию команда For использует в качестве разделителя символ пробела, что вызовет затруднения, если потребуется выделить из данных только третий столбец.

Экран. Пример работы Reg Query 

Рассмотрим, например, первую строку данных, показанных на экране. Она содержит значение Microsoft Office XP Professional, однако для команды For третьим столбцом — или маркером (token), пользуясь терминами команды For, — будет только слово Microsoft. Соответственно, чтобы отобразить строку Microsoft Office XP Professional целиком, нужно будет вывести в строке третий, четвертый, пятый и шестой маркеры.
Разумеется, мы не можем прогнозировать, сколько слов будет содержать имя приложения, но можно учесть тот факт, что это имя всегда находится в конце потока выходных данных, начиная с третьего слова. Таким образом, в сценарии была реализована команда, которая извлекает из данных полное имя приложения. В данной строке ключ «Tokens=1,2,*» %%i указывает команде For, что необходимо записывать значения из столбца 1 в переменную %%i, значения из столбца 2 — в переменную %%j, а весь остальной текст, начиная с третьего слова, в переменную %%k. При этом, если необходимо удалить из выводимых данных строки «REG_SZ» и «Displayname», это означает, что надо выводить только третий маркер. А поскольку отсчет маркеров начинается с переменной %%i, третий маркер будет находиться в переменной %%k.
Переменная %%k представляет собой параметр, который передается в раздел сценария, обозначенный меткой :getpathname. Данный раздел обеспечивает вывод имени приложения. В принципе этот раздел можно игнорировать и включить в сценарий отдельную секцию, в которой вывод имени приложения будет осуществлять команда ECHO, размещаемая внутри цикла For. Однако я так делать не стал, поскольку некоторые программы не имеют отображаемого имени, следовательно, в подобных случаях переменная %%k будет иметь пустое значение. Код раздела :getappname обрабатывает данную ситуацию. Вместо того чтобы отображать пустую строку в случае, когда значение displayname отсутствует, сценарий переходит в конец файла и завершается.

Запуск сценария

Для запуска сценария QueryInstalled Software.cmd необходимо соблюдать единственное условие: утилита reg.exe должна находиться либо в том же каталоге, что и сам файл сценария, либо путь к ней должен быть описан в пользовательской или системной переменной PATH. Тестирование работы сценария выполнялось на системах Windows 2000 SP3 и SP4, а также на системах Windows NT 4.0 SP6a. Данный сценарий также должен работать и на системе Windows XP, однако следует иметь в виду, что, хотя в XP имеется встроенная команда reg.exe, эта ее версия не позволяет обращаться к удаленным компьютерам. Так что для опроса удаленных серверов и рабочих станций необходимо использовать ту версию reg.exe, которая имеет параметр computername.

Практическое применение сценария

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

Стив Сегьюс (scriptmaster@scripthorizon.com) — консультант компании RCG Information Technology в Нью-Йорке. Имеет сертификаты MCP, MCSE и является сертифицированным программистом по Java2