PowerShell-скрипт для інвентаризації Windows ПК збирає по LAN базові дані з хостів через WinRM і складає їх у CSV: ім’я, версію Windows, IP-адреси, RAM і логічні диски. Цього вистачає для невеликого парку, де потрібен швидкий зріз без агента, RMM і окремої CMDB.
Тут усе тримається на доступі до вузлів. Працюючий WinRM, відкритий firewall і коректні права дають нормальний звіт. Якщо одна з цих умов випадає, частина машин зникає або повертає порожні поля.
Що реально дає збір даних через WinRM
Через віддалений PowerShell-запит можна зібрати базовий технічний портрет машини: hostname, caption і version ОС, IPv4-адреси, сумарний обсяг RAM, літери дисків, їхній розмір і вільне місце. Для швидкого аудиту цього зазвичай достатньо, якщо мета – побачити склад парку і знайти вузли, що вибиваються з норми.
Найчастіше такий звіт потрібен після переїзду, сегментації або масового оновлення. Ще один типовий сценарій – підготовка до бекапів, моніторингу чи політик оновлення. Добре видно машини зі старою збіркою Windows, дивним набором дисків або адресами, що не збігаються з очікуваними.
Обмеження тут теж прості. Скрипт не веде історію змін і не вирішує проблему недоступних вузлів. Якщо потрібен постійний контроль стану, поруч зазвичай з’являється або моніторинг домашнього сервера, або окремий контур автоматизації під звіти й сповіщення.
Які умови потрібні для опитування вузлів у LAN
Для віддаленого збору потрібні ввімкнений WinRM, дозволений трафік у firewall, обліковий запис з правами на віддалений доступ і спосіб коректно знайти вузол через DNS або список імен. Без цього PowerShell-скрипт для інвентаризації Windows ПК працює уривками.
Що має бути ввімкнено на цільових машинах
На кожному Windows ПК має працювати служба WinRM. Базове ввімкнення роблять так:
Enable-PSRemoting -Force
Команда налаштовує listener, правила firewall і готує систему до PowerShell Remoting. На клієнтських редакціях Windows проблема часто впирається в мережевий профіль. Якщо інтерфейс позначений як Public, винятки можуть не спрацювати як треба.
Яким обліковим записом запускати збір
Найменше сюрпризів дає доменний обліковий запис з правами локального адміністратора на цільових ПК. У робочій групі все жорсткіше: локальні акаунти, UAC remote restrictions і різні паролі на машинах швидко ламають масовий опитувач.
У недоменній мережі краще одразу закласти окремий технічний акаунт з однаковими обліковими даними на всіх вузлах. Інакше один ПК відповість, другий поверне Access is denied, а третій зависне на аутентифікації.
DNS чи файл зі списком хостів
Найстабільніше подавати в скрипт список імен хостів із текстового файла. DNS корисний, але в невеликих LAN часто виявляється неакуратним: стара A-запис, перейменований ПК або дубль після перевстановлення системи. Список хостів простіше контролювати.
Якщо частина машин доступна лише по IP, краще використовувати імена там, де це можливо, а IP лишити запасним варіантом. Для інвентаризації IP варто збирати із самої системи, а не вважати правильним той, за яким вузол опитували.
Готовий скрипт з вивантаженням у CSV
Нижче готовий варіант, який читає список хостів із файла, опитує кожен вузол через WinRM, збирає базові параметри і пише результат у CSV. Недоступні машини теж потрапляють у звіт зі статусом помилки, тому один мертвий хост не валить весь запуск.
$Computers = Get-Content -Path ".\hosts.txt" | Where-Object { $_.Trim() -ne "" }
$Credential = Get-Credential
$SessionOption = New-PSSessionOption -OpenTimeout 5000 -OperationTimeout 10000
$Results = foreach ($Computer in $Computers) {
try {
$Data = Invoke-Command -ComputerName $Computer -Credential $Credential -SessionOption $SessionOption -ErrorAction Stop -ScriptBlock {
$os = Get-CimInstance Win32_OperatingSystem
$cs = Get-CimInstance Win32_ComputerSystem
$nics = Get-CimInstance Win32_NetworkAdapterConfiguration | Where-Object {
$_.IPEnabled -eq $true -and $_.IPAddress
}
$ipv4 = @()
foreach ($nic in $nics) {
$ipv4 += ($nic.IPAddress | Where-Object { $_ -match '^\d{1,3}(\.\d{1,3}){3}$' })
}
$disks = Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" | ForEach-Object {
"{0} {1:N1} GB free of {2:N1} GB" -f $_.DeviceID, ($_.FreeSpace / 1GB), ($_.Size / 1GB)
}
[PSCustomObject]@{
Hostname = $env:COMPUTERNAME
OSName = $os.Caption
OSVersion = $os.Version
IPv4 = ($ipv4 -join ", ")
RAM_GB = [math]::Round($cs.TotalPhysicalMemory / 1GB, 2)
Disks = ($disks -join "; ")
Status = "OK"
}
}
$Data
}
catch {
[PSCustomObject]@{
Hostname = $Computer
OSName = ""
OSVersion = ""
IPv4 = ""
RAM_GB = ""
Disks = ""
Status = $_.Exception.Message
}
}
}
$Results | Export-Csv -Path ".\windows_inventory.csv" -NoTypeInformation -Encoding UTF8
У файлі hosts.txt має бути один хост на рядок. Наприклад:
pc-01 pc-02 ws-admin 192.168.1.45
Скрипт навмисно збирає диски в один рядок. Для Excel це зручніше, ніж вкладені об’єкти або окремий файл на кожен вузол. Якщо потрібна нормалізована структура для подальшої обробки, диски краще вивантажувати в окремий CSV з колонками Hostname, DriveLetter, SizeGB і FreeGB.
Є й неочевидна межа. Якщо на ПК кілька активних адаптерів – Ethernet, Wi‑Fi, VPN або vEthernet Hyper-V – поле IPv4 поверне кілька адрес. Для інвентаризації це корисніше, ніж намагатися вгадати одну головну адресу, але CSV доведеться фільтрувати уважніше.
Запуск по списку хостів без довгих затримок
Масовий запуск зазвичай ламається на таймаутах. Якщо подавати в опитування сирий діапазон IP або старий список DNS-імен, PowerShell витратить більшість часу на вузли, яких уже немає. Тому список хостів краще чистити заздалегідь, а для сесії ставити короткі таймаути.
Чому список імен кращий за перебір підмережі
Перебір усієї підмережі виглядає зручно, але для WinRM він повільний. На локалці з десятками адрес це ще терпимо. Коли в сегменті багато вимкнених ПК, принтерів, камер і чужих пристроїв, опитування перетворюється на очікування відмов.
Краще мати актуальний hosts.txt і час від часу звіряти його з DHCP, AD або фактичним списком робочих станцій. Для суміжних задач може знадобитися й інвентаризація віртуальних машин, якщо частина Windows-хостів живе у віртуалізації, а не на фізичних ПК.
Які таймаути залишити в сценарії
У скрипті вище OpenTimeout встановлений у 5 секунд, а OperationTimeout – у 10. Для LAN цього зазвичай достатньо. Якщо мережа повільна або між VLAN стоїть жорстка фільтрація, межі можна трохи підняти, але великі значення лише маскують проблему.
Перед WinRM інколи корисно перевіряти доступність вузла через Test-Connection з одним або двома echo request. Це скорочує час на повністю мертві адреси, але не замінює перевірку WinRM: хост може відповідати на ICMP і не приймати PowerShell Remoting.
$AliveHosts = foreach ($Computer in $Computers) {
if (Test-Connection -ComputerName $Computer -Count 1 -Quiet) {
$Computer
}
}
$AliveHosts
Для регулярних запусків краще винести перевірки в окремий технічний сценарій. Якщо потрібні звіти за розкладом, лог помилок і повідомлення про збої, стане в пригоді автоматизація перевірок через скрипти.
Перевірка CSV і контрольних вузлів
Перевірка проста: відкрити CSV і звірити кілька контрольних машин руками. Насамперед дивляться на поле Status, потім на IP, RAM і список дисків. Якщо хоча б на двох-трьох вузлах значення збігаються з локальними даними, механіка збору працює коректно.
Швидка валідація через Import-Csv
Перший крок – переконатися, що файл не містить порожніх рядків зі статусом OK. Такий симптом часто вказує на кривий ScriptBlock або поламане перетворення масивів у рядок.
$Inventory = Import-Csv .\windows_inventory.csv
$Inventory | Select-Object Hostname, IPv4, RAM_GB, Disks, Status | Format-Table -AutoSize
$Inventory | Where-Object { $_.Status -ne "OK" } | Format-Table Hostname, Status -AutoSize
$Inventory | Where-Object { [string]::IsNullOrWhiteSpace($_.IPv4) -and $_.Status -eq "OK" }
Якщо поле IPv4 порожнє, а статус успішний, проблема зазвичай у мережевих адаптерах або фільтрації адрес. Так буває, коли машина має лише IPv6 або потрібний інтерфейс вимкнений під час запиту.
Що звіряти на самій машині
На одному з ПК варто звірити локальні значення командами hostname, ipconfig, systeminfo і переглядом дисків у Get-Volume або Провіднику. Розбіжність у RAM на кілька сотень мегабайт допустима, якщо система резервує пам’ять під відео або firmware. Розбіжність у дисках уже вказує, що збір пішов не туди.
Коли для доступу до хостів уже налаштований SSH, інколи простіше окремо тримати й OpenSSH Server на Windows 11 для аварійної перевірки вузла, якщо WinRM не відповідає, а до консолі далеко.
Де зазвичай ламається збір через WinRM
Найчастіше інвентаризація валиться в трьох точках: WinRM не налаштований, firewall блокує трафік або обліковий запис не має прав на віддалений виклик. Сам скрипт у таких випадках другорядний. Проблема майже завжди сидить у базовій інфраструктурі доступу.
WinRM не слухає або слухає не там
Перевірити це можна локально на цільовому ПК:
winrm quickconfig Test-WSMan localhost
Якщо Test-WSMan локально не проходить, віддалене опитування теж не піде. Після ввімкнення WinRM на клієнтських системах іноді лишається старий мережевий профіль Public, і правила доступу не застосовуються як потрібно.
Access is denied при правильному паролі
Тут зазвичай винен не пароль, а UAC і віддалені обмеження локальних адміністраторів у workgroup. У домені таких сюрпризів менше. Для невеликої локалки без AD найстабільніший варіант – уніфікований технічний акаунт і однакова політика доступу на всіх ПК.
Ще одна типова помилка – запуск консолі PowerShell без підвищення прав на машині, з якої йде опитування. Частина вузлів відповість, частина ні, і звіт вийде брудний.
Порожні диски або дивні IP у звіті
Порожні поля дисків часто з’являються на системах із проблемами WMI/CIM. Якщо Get-CimInstance Win32_LogicalDisk локально повертає помилки, лагодити треба сам вузол. З IP ситуація інша: кілька адрес у полі зазвичай означають додаткові адаптери, а не помилку сценарію.
PowerShell-скрипт для інвентаризації Windows ПК погано переносить мережевий зоопарк із VPN-клієнтів, віртуальних свічів і напіввидалених драйверів NIC. У такому середовищі нормалізація інтерфейсів часто дає більше користі, ніж чергова правка CSV.
Коли скрипта вистачає, а коли вже ні
PowerShell-скрипт для інвентаризації Windows ПК добре підходить для невеликого парку, де список вузлів відомий, а доступ через WinRM уже наведений до ладу. Для кількох десятків машин це швидкий і дешевий варіант. Після сотні вузлів основні проблеми створює вже не PowerShell, а підтримка середовища.
| Масштаб | Що працює нормально | Де починаються проблеми |
|---|---|---|
| До 20 ПК | Ручний список хостів, запуск із консолі, CSV в Excel | Переважно права доступу і поодинокі вузли без WinRM |
| 20-50 ПК | Періодичний запуск за розкладом, базова фільтрація помилок | Старі записи DNS, різні профілі мережі, накопичення винятків |
| 50+ ПК | Лише як допоміжний інструмент для разових вибірок | Керування обліковками, історія змін, контроль агентів, звітність |
Після позначки в кілька десятків машин головний біль створює якість середовища: хто увімкнув WinRM, хто змінив пароль, який хост переїхав в інший VLAN, де зламався DNS. Для такого масштабу вже краще мати централізований inventory або RMM, який тримає стан вузлів постійно.
Для разового або періодичного збору по LAN цей підхід виправданий. Коли потрібна історія змін, прив’язка до користувача, софту і подій, CSV закінчується дуже швидко.
Коментарі
Коментарів ще немає. Обговорення - у Telegram.