Які програми встановлені на комп'ютерам вашої мережі?

  1. Клас Win32_Product або реєстр
  2. Як працювати зі сценарієм Get-InstalledApp.ps1
  3. Внутрішні механізми сценарію Get-InstalledApp.ps1

Системним адміністраторам часто доводиться визначати, які програми встановлені на комп'ютерах, що обслуговуються ними мереж. Існує цілий ряд обставин, які змушують їх регулярно проводити аудит додатків, встановлених на корпоративних системах. Буває, що адміністратор встановлює програмний пакет, забуває його задокументувати, а пізніше виявляється, що в системі безпеки пакету є вразливі місця. Іноді користувачі наділяються адміністративними правами, що дозволяють їм самостійно встановлювати програмні продукти на свої комп'ютери. Існує і така небезпека: користувач, самовільно привласнив повноваження адміністратора, може встановити несанкціоноване програмне забезпечення, відкриваючи тим самим можливість залучення організації до судової відповідальності.

Незалежні провайдери пропонують кошти для моніторингу встановленого програмного забезпечення, але у невеликих підприємств може не виявитися ресурсів для реалізації такого рішення. У нашій компанії не було програмного засобу аудиту, тому я написав сценарій Windows PowerShell Get-InstalledApp.ps1 (див. лістинг ). Перед тим як приступити до опису процедури використання цього сценарію і механізму його роботи, мені б хотілося зупинитися на двох методах виявлення встановленого програмного забезпечення за допомогою сценарію і пояснити, чому мене привернув той метод, на якому я зупинив вибір.

Клас Win32_Product або реєстр

В інструментарії управління Windows Management Instrumentation (WMI) є клас Win32_Product, який дозволяє реєструвати додатки, встановлені на комп'ютері. У середовищі PowerShell ця можливість реалізується просто. Так, команда

Get-WmiObject Win32_Product
| select name

генерує список всіх додатків, встановлених на досліджуваному в даний момент комп'ютері. Однак треба сказати, що класу Win32_Product притаманний ряд обмежень.

  • Він зчитує імена лише тих програм, які були встановлені за допомогою служби Windows Installer. Імена додатків, встановлених іншими способами, за допомогою даного класу не зчитуються. Це означає, що використання класу Win32_Product з метою здійснення спільного аудиту програмних засобів неможливо, крім тих випадків, коли для установки пакетів використовується виключно інсталятор Windows, а це практично нездійсненно для більшості мереж.
  • Зчитування примірників класу Win32_Product виконується досить повільно.
  • Не завжди можливо зчитування примірників класу Win32_Product з віддалених комп'ютерів. Так, коли я намагаюся виконати подібну процедуру в своїй мережі, то отримую повідомлення про помилку Generic failure.

Через перерахованих проблем доцільність застосування класу WMI Win32_Product знижується. Однак є альтернативний метод отримання інформації про встановлені додатках - безпосередньо з реєстру. Дані про встановлені на комп'ютері програм існують у розділі реєстру HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Uninstall. У кожному підрозділі розділу Uninstall представлено встановлений додаток, а значення в кожному підрозділі відображають інформацію про відповідній програмі, як показано на екрані. Таким чином, щоб отримати список додатків, можна «прочесати» розділ Uninstall і вважати дані кожного підрозділу, що входить в розділ Uninstall.

Провайдер реєстру PowerShell дає можливість виконувати команду Get-ChildItem для отримання списку імен додатків, встановлених на досліджуваному комп'ютері:

Get-ChildItem HKLM: \ SOFTWARE \
Microsoft \ Windows \ CurrentVersion \
Uninstall |
ForEach-object {(Get-ItemProperty
Microsoft.PowerShell.Core \ Registry :: $ _).
DisplayName}

Однак в середовищі PowerShell 1.0 команда Get-ChildItem не забезпечує доступ до провайдера реєстру на віддаленому комп'ютері, тому для досягнення мети адміністратору доводиться задіяти StdRegProv, клас управління реєстром інструментарію WMI. Клас StdRegProv передбачає можливість використання корисного набору методів, що полегшують зчитування реєстру незалежно від того, з якою системою здійснюється взаємодія, локальної або віддаленої. Додаткову інформацію про клас StdRegProv можна знайти на сторінці StdRegProv Class на сайті MSDN ( http://msdn.microsoft.com/en-us/library/aa393664.aspx ).

Як працювати зі сценарієм Get-InstalledApp.ps1

Сценарій Get-InstalledApp.ps1 зчитує інформацію про встановлені додатках з реєстру, після чого повертає або список всіх встановлених додатків, або список програм, що відповідають заданим критеріям. У сценарії використовується наступний синтаксис командного рядка:

Get-InstalledApp [-computername]
[-appID] [-appname]
[-publisher] [-version] [-matchall]

Параметр computername використовується для виведення списку, що складається з одного імені комп'ютера або зі списку імен комп'ютерів. Параметр computername є першим за рахунком, тому для скорочення команди ви можете опустити ключ -computername і просто включити в команду ім'я комп'ютера. Якщо ж повністю виключити цей параметр, сценарій буде виходити з того, що ви хочете отримати дані по локальному комп'ютеру.

Параметр -appID використовується для пошуку додатків по їх ідентифікаторів (application ID). Ідентифікатор додатка - це підрозділ реєстру, що відноситься до розділу Uninstall. На екрані ідентифікатор додатки виділений в лівій панелі. Для додатків, встановлених за допомогою інсталятора Windows, ідентіфікактор додатки еквівалентний глобальному унікальним ідентифікатором (ідентифікатором GUID) ID продукту у відповідній програмі. Використання параметра -appID - кращий спосіб виявлення конкретних програм, встановлених за допомогою служби Windows Installer.

Параметр -appname застосовується для пошуку додатків по їх псевдонімом. Псевдонім - це назва програми в тому вигляді, в якому воно з'являється в списку Add / Remove Programs або значення DisplayName в підрозділі у відповідній програмі. Так, на екрані виділене програма має власний псевдонім OpenOffice.org 2.4.

Параметр -publisher використовується для пошуку додатків по видавцеві. Якщо у вас немає точних відомостей про те, хто є видавцем додатки, ви можете знайти їх в запису Publisher підрозділу реєстру для цього додатка. Так, видавцем виділеного додатки на екрані є OpenOffice.org.

Параметр -version використовується для пошуку додатків по їх версіями. Якщо ви не знаєте напевно, яка версія того чи іншого додатка, можете вважати ці дані з параметра DisplayVersion підрозділу цього додатка. Наприклад, додаток, виділене на екрані, має версію 2.4.9286.16.

Якщо для файлу Get-InstalledApp.ps1 вказати ключ -matchall, сценарій буде виводити всі відповідні заданому критерію додатки, замість того щоб припинити пошук після виявлення першого відповідності. Так, команда

Get-InstalledApp -publisher
"Microsoft Corporation" -matchall

поверне список всіх додатків Microsoft, встановлених на досліджуваному комп'ютері. Якщо ж ви опустите ключ -matchall, сценарій припинить пошук після виявлення першого відповідності.

Всі перераховані ключі (-appID, -appname, -publisher і -version) - підтримують пошук з використанням символів шаблонів; аргументи ключів нечутливі до регістру. Так, команда

Get-InstalledApp -appname
"* office *" -matchall

виводить список всіх встановлених на досліджуваному комп'ютері додатків, в іменах яких є слово office. Крім того, для вказівки більш деталізованих критеріїв пошуку можна вказувати параметри -appID, -appname, -publisher і -version в будь-яких поєднаннях. Так, команда

Get-InstalledApp sales01-appname
"* .NET Framework *" -version "2 *"

виводить перший додаток, що містить слова .NET Framework в видимій частині імені і має версію, номер якої починається з цифри 2. Якщо додатки, що відповідають зазначеним критеріям, не виявлені, сценарій не повертає будь-яких значень. Для отримання додаткових відомостей про шаблонних символах в середовищі PowerShell, виконайте команду

Get-Help about_wildcard

Сценарій Get-InstalledApp.ps1 повертає об'єкти, що містять властивості ComputerName, AppID, AppName, Publisher і Version, тому ви можете використовувати команди PowerShell і форматувати вихідні дані відповідно до своїх потреб. Так, команда

Get-InstalledApp | Select-Object AppName,
Version |
Sort-Object AppName

виводить список програм і версію кожної програми, відсортовані по іменах додатків. Щоб за допомогою значень, розділених комами, створити звіт по всім програмним продуктам, встановленим на всіх комп'ютерах, які перераховані у файлі Computers.txt, потрібно використовувати команду

Get-InstalledApp (Get-Content
Computers.txt) |
Export-CSV Report.csv -notypeinformation

Параметр -NoTypeInformation команди Export-CSV блокує передачу інформації у вихідний файл CSV. команда

Get-InstalledApp (Get-Content
Computers.txt)
-appID "{7131646D-CD3C-40F4-97B9-
CD9E4E6262EF} "|
Select-Object ComputerName

формує список згаданих у файлі Computers.txt комп'ютерів, на яких встановлена ​​бібліотека .NET Framework 2.0. Якщо ви хочете отримати впорядкований список встановлених на досліджуваній системі додатків Microsoft і їх версії, відсортовані по іменах додатків, скористайтеся командою

Get-InstalledApp -publisher
"Microsoft Corporation" -matchall |
Select-Object AppName, Version |
Sort-Object AppName

Внутрішні механізми сценарію Get-InstalledApp.ps1

Тепер, коли ви знаєте, як користуватися сценарієм Get-InstalledApp.ps1, давайте подивимося, яким чином він функціонує. Спочатку за допомогою команди param сценарій оголошує параметри командного рядка; потім він створює дві глобальні змінні для використання в подальшому при роботі з класом StdRegProv. Після цього сценарій оголошує функцію usage і головну функцію. Останній рядок сценарію викликає головну функцію.

Функція main містить основне тіло сценарію. Перш за все, вона з'ясовує, чи є в командному рядку параметр -help. Якщо так, то функція main викликає функцію usage, яка генерує повідомлення про використання і завершує виконання сценарію.

Далі основна функція створює порожню хеш-таблицю і зберігає її в змінній $ propertyList, як показано у фрагменті А лістингу .

Якщо в командному рядку є хоча б один з параметрів (-appID, -appname, -publisher або -version), функція додає до хеш-таблиці ключ, відповідний імені параметра, і задає значення цього ключа аргументу параметра. Так, команда

Get-InstalledApp -appname
"Windows Support Tools"

наказує головної функції заповнити хеш-таблицю за допомогою ключа AppName, який має значення Windows Support Tools.

Потім функція main з'ясовує, чи є порожнім параметр computername. Якщо параметр порожній, функція використовує ім'я локального комп'ютера, яке вона отримує з змінної середовища COMPUTERNAME. Якщо ж параметр не є порожнім, функція перебирає масив імен комп'ютерів за допомогою циклу foreach. Цикл виконується тільки раз, якщо аргумент computername параметра є ім'я одного комп'ютера.

Всередині циклу foreach функція main оголошує змінну $ err і задає її значення рівним $ NULL. Після цього за допомогою спеціального блоку сценарію (trap scriptblock) функція виявляє помилки WMI, як показано у фрагменті B лістингу . При виникненні помилки «ловушечний» блок сценарію оновлює змінну помилки до рівня поточної записи помилки (тобто задає їй значення $ ERROR [0]) і продовжує виконання команди, наступної за помилкою.

Далі основна функція підключається до класу StdRegProv на досліджуваному комп'ютері за допомогою прискорювача типу [WMIClass] для класу System.Management.ManagementClass платформи Windows.NET Framework. У разі виникнення помилки остання виявляється за допомогою спеціального блоку сценарію, представленого у фрагменті C лістингу . Якщо значення змінної $ err не дорівнює $ NULL, це означає, що був запущений «ловушечний» блок сценарію. У цьому випадку функція main формує запис про помилку за допомогою команди Write-Error, а потім використовує команду continue, що дозволяє пропустити решту циклу foreach і перейти до наступного імені комп'ютера в масиві.

Після цього функція main використовує метод EnumKey класу StdRegProv для перерахування підрозділів розділу Uninstall. Результат застосування методу EnumKey - масив імен підрозділів - зберігається у властивості sNames. Далі функція перебирає масив імен підрозділів за допомогою іншого циклу foreach.

При обробці кожного представленого в масиві імені підрозділу функція main за допомогою методу GetStringValue класу StdRegProv зчитує властивість DisplayName відповідного розділу реєстру. Використовуючи команду Join-Path, функція приєднує ім'я підрозділу до ключу Uninstall. Утворений в результаті маршрут до реєстру використовується як аргумент для методу GetStringValue, який повертає значення запису реєстру. Це повинно бути строкове значення. Даний метод приймає три аргументи: гілка реєстру, шлях до розділу і ім'я параметра. Значення GetStringValue повертає об'єкт, що містить дві властивості: властивість ReturnValue, яке включає значення, яке вказує на успішний або невдалий виклик методу, і властивість sValue, що містить строкове значення. Функція main привласнює значення властивості sValue змінної $ name.

Якщо значення змінної $ name не дорівнює $ NULL, функція main створює настроюється вихідний об'єкт, що містить чотири властивості: ComputerName, AppID, AppName, Publisher і Version. Вона оновлює властивість об'єкта ComputerName ім'ям досліджуваного комп'ютера, властивість об'єкта AppID - ім'ям поточного підрозділу, а властивість об'єкта AppName - відображуваним ім'ям поточного додатка. Далі функція двічі застосовує метод GetStringValue з метою вилучення значень записів Publisher і DisplayVersion для поновлення відповідних властивостей в розширеному об'єкті за допомогою цих значень.

Отже, функція main завершила отримання інформації про поточний додатку і тепер перевіряє хеш-таблицю $ propertyList на наявність ключів; для цього перевірці піддається властивість Count колекції Keys. Якщо таблиця хеширования не містить ключів (інакше кажучи, якщо в командному рядку не представлений жоден з параметрів (-appID, -appname, -publisher і -version)), тоді функція просто генерує настроюється об'єкт, щоб з'ясувати, аргументи якого параметра командного рядка відповідають значенням властивостей настроюється об'єкта. фрагмент D лістингу демонструє, яким чином функція main вирішує цю задачу.

Спочатку значення змінної $ matches задається рівним 0, потім код проходить по всіх елементах колекції Keys хеш-таблиці $ propertyList. Для кожного ключа в таблиці хеширования $ propertyList функція застосовує оператор середовища PowerShell -like, щоб з'ясувати, чи відповідає ця властивість настроюється об'єкта рівносильному значенням хеш-таблиці $ propertyList hashtable. У разі відповідності значень зазначених елементів функція збільшує значення змінної $ matches. Якщо число відповідностей дорівнює числу ключів в таблиці хешування, функція main формує настроюється об'єкт. Нарешті, якщо в командному рядку відсутня параметр -matchall, функція використовує команду break для виходу з циклу foreach, який застосовується для перебору підрозділів реєстру.

Таким чином, сценарій Get-InstalledApp.ps1 дозволяє без особливих клопотів отримати список додатків, встановлених на одному або декількох комп'ютерах. Більш того, він може організувати пошук заданих додатків. Можливо, для моніторингу програмних засобів, встановлених на комп'ютерах вашої мережі, цілком можна буде обійтися даним сценарієм.

Білл Стюарт ( [email protected] ) - системний і мережевий адміністратор компанії French Mortuary (Нью-Мехіко)

Лістинг. Сценарій Get-InstalledApp.ps1