PowerShell provides built-in cmdlets and access to the Common Information Model (CIM) to query, monitor, and manage physical hardware, system firmware, storage drives, and Plug and Play (PnP) peripherals.
Plug and Play (PnP) Device Management
The PnpDevice module provides cmdlets to inspect and change the state of hardware peripherals managed by the Windows Plug and Play subsystem (such as network adapters, USB controllers, audio devices, and Bluetooth radios).
Listing Devices with Get-PnpDevice
The Get-PnpDevice cmdlet enumerates connected and historical PnP devices:
Get-PnpDevice -Class "Net" -Status "OK" | Select-Object -First 3Status Class FriendlyName InstanceId
------ ----- ------------ ----------
OK Net Intel(R) Ethernet Connection (7) I219-V PCI\VEN_8086&D...
OK Net WAN Miniport (IP) SWD\MSRRAS\WAN...
OK Net WAN Miniport (IPv6) SWD\MSRRAS\WAN...Key filtering parameters:
-Class: Filters devices by hardware category (e.g.,Net,USB,Bluetooth,Display,Media).-Status: Filters by operating state (e.g.,OK,Error,Degraded,Unknown).-PresentOnly: Restricts the query to devices currently attached and powered on, excluding disconnected peripheral history.
To find all malfunctioning or erroring devices across the system:
Get-PnpDevice -PresentOnly | Where-Object { $_.Status -ne "OK" }Status Class FriendlyName InstanceId
------ ----- ------------ ----------
Error USB Unknown USB Device (Device Descriptor Request Failed) USB\VID_0000...Enabling and Disabling Devices
Hardware devices can be turned on or off programmatically using Disable-PnpDevice and Enable-PnpDevice. These are equivalent to right-clicking a device in Device Manager and selecting Enable or Disable.
$TargetDevice = Get-PnpDevice -FriendlyName "*Bluetooth Adapter*" -PresentOnly
Disable-PnpDevice -InstanceId $TargetDevice.InstanceId -Confirm:$falseTo re-enable the device:
Enable-PnpDevice -InstanceId $TargetDevice.InstanceId -Confirm:$falsewhere:
-InstanceIduniquely identifies the device in the Windows hardware registry tree (retrieved fromGet-PnpDevice).-Confirm:$falsesuppresses the interactive confirmation prompt, useful for unattended scripts.
Hardware Auditing with Get-CimInstance
To query core system specifications (motherboard, CPU, memory modules, firmware), use Get-CimInstance. This cmdlet queries CIM/WMI classes using modern, firewall-friendly WS-Management protocols.
Common CIM Classes
| Hardware Target | CIM Class Name | Useful Properties |
|---|---|---|
| System Identity | Win32_ComputerSystem |
Manufacturer, Model, TotalPhysicalMemory, NumberOfProcessors |
| Processor | Win32_Processor |
Name, NumberOfCores, NumberOfLogicalProcessors, MaxClockSpeed |
| Firmware / BIOS | Win32_BIOS |
Manufacturer, SMBIOSBIOSVersion, SerialNumber, ReleaseDate |
| Physical RAM | Win32_PhysicalMemory |
Capacity, Speed, Manufacturer, PartNumber, DeviceLocator |
| Motherboard | Win32_BaseBoard |
Manufacturer, Product, SerialNumber |
| Operating System | Win32_OperatingSystem |
Version, InstallDate, LastBootUpTime |
| Logical Disk | Win32_LogicalDisk |
Legacy disk/partition information |
| Network Adapter | Win32_NetworkAdapter |
Network adapter details |
Quick Queries
Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object Manufacturer, Model, TotalPhysicalMemoryManufacturer Model TotalPhysicalMemory
------------ ----- --------------------
Dell Inc. OptiPlex 7090 17179869184Get-CimInstance -ClassName Win32_Processor | Select-Object Name, NumberOfCores, MaxClockSpeedName NumberOfCores MaxClockSpeed
---- ------------- -------------
Intel(R) Core(TM) i7-10700 CPU @ 2.90GHz 8 2904Get-CimInstance -ClassName Win32_BIOS | Select-Object Manufacturer, SMBIOSBIOSVersion, ReleaseDateManufacturer SMBIOSBIOSVersion ReleaseDate
------------ ----------------- -----------
Dell Inc. 2.14.0 8/15/2023 12:00:00 AMCombined Hardware Metadata Script
$Bios = Get-CimInstance -ClassName Win32_BIOS
$Cpu = Get-CimInstance -ClassName Win32_Processor
[PSCustomObject]@{
Manufacturer = $Bios.Manufacturer
BIOSVersion = $Bios.SMBIOSBIOSVersion
SerialNumber = $Bios.SerialNumber
Processor = $Cpu.Name
PhysicalCores = $Cpu.NumberOfCores
LogicalCores = $Cpu.NumberOfLogicalProcessors
}pwsh ./query-bios.ps1Manufacturer : Dell Inc.
BIOSVersion : 1.15.1
SerialNumber : 8XYZ123
Processor : 12th Gen Intel(R) Core(TM) i7-12700
PhysicalCores : 12
LogicalCores : 20Storage Subsystem: Get-Disk and Get-Volume
PowerShell separates storage architecture into two layers:
- Physical Disks (
Get-Disk): Represents the raw physical drive, NVMe SSD, or virtual hard disk (VHD) hardware. - Logical Volumes (
Get-Volume): Represents the formatted file system partitions (C:,D:) residing on those physical disks.
Querying Physical Disks with Get-Disk
Get-Disk retrieves physical drive metadata, partition styles, and operational health:
Get-DiskNumber Friendly Name Serial Number HealthStatus OperationalStatus Total Size Partition
Style
------ ------------- ------------- ------------ ----------------- ---------- ----------
0 Samsung SSD 980 PRO 1TB S5GXNF0R123456 Healthy Online 931.51 GB GPT
1 Crucial CT2000P3SSD8 2240E6789012 Healthy Online 1.82 TB GPTKey properties to monitor:
HealthStatus: Reports SMART status (Healthy,Warning,Unhealthy).OperationalStatus: Reports device link status (Online,Offline,Read Only).PartitionStyle: Displays modernGPTor legacyMBR.
Querying Logical Volumes with Get-Volume
Get-Volume inspects formatted file systems, partition labels, and remaining free space:
Get-VolumeDriveLetter FriendlyName FileSystemType DriveType HealthStatus OperationalStatus SizeRemaining Size
----------- ------------ -------------- --------- ------------ ----------------- ------------- ----
C OS NTFS Fixed Healthy OK 145.22 GB 930.85 GB
D DataStore ReFS Fixed Healthy OK 1.25 TB 1.82 TB
Recovery NTFS Fixed Healthy OK 85.4 MB 650 MBPractical Example: Automated Hardware Health and Peripheral Audit
The following script audits physical hardware specifications, verifies disk health, and flags any failing Plug and Play devices:
$System = Get-CimInstance -ClassName Win32_ComputerSystem
$Processor = Get-CimInstance -ClassName Win32_Processor | Select-Object -First 1
$UnhealthyDisks = Get-Disk | Where-Object { $_.HealthStatus -ne "Healthy" -or $_.OperationalStatus -ne "Online" }
$FailedPeripherals = Get-PnpDevice -PresentOnly | Where-Object { $_.Status -notin @("OK", "Degraded") }
[PSCustomObject]@{
Hostname = $System.Name
Model = "$($System.Manufacturer) $($System.Model)"
CPU = $Processor.Name.Trim()
TotalRAM_GB = [math]::Round($System.TotalPhysicalMemory / 1GB, 2)
TotalPhysicalDisks = (Get-Disk).Count
DisksDegraded = $UnhealthyDisks.Count
PeripheralsInError = $FailedPeripherals.Count
SystemHealthy = ($UnhealthyDisks.Count -eq 0 -and $FailedPeripherals.Count -eq 0)
AuditTimestamp = (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
}where:
Get-CimInstancequeries identity and core processor details.Get-Disk | Where-Object ...filters for any drive exhibiting hardware failure or an offline state.Get-PnpDevice -PresentOnlyscans attached hardware for error states.[PSCustomObject]compiles the metrics into a single inventory record.
Run the script from the console:
pwsh ./audit-device-health.ps1Hostname : WORKSTATION-01
Model : Dell Inc. Precision 3660
CPU : 12th Gen Intel(R) Core(TM) i7-12700
TotalRAM_GB : 31.68
TotalPhysicalDisks : 2
DisksDegraded : 0
PeripheralsInError : 0
SystemHealthy : True
AuditTimestamp : 2026-10-24 18:20:15