What “system insights” means in PowerShell
System insights are small, repeatable checks you can run to answer common troubleshooting and inventory questions: What OS is this? How long has it been running? How much disk and memory is available? What IP settings are active? Are there relevant errors in the logs? In this chapter you’ll use read-only cmdlets to collect that information consistently, and you’ll build a simple “system snapshot” you can share with someone else.
Modern sources of system data: cmdlets vs. CIM/WMI
PowerShell can read system information from multiple sources:
- Purpose-built cmdlets (for example
Get-ComputerInfo,Get-NetIPConfiguration,Get-WinEvent) are usually the simplest and most readable. - CIM (Common Information Model) via
Get-CimInstancereads standardized classes (often the same underlying data that older WMI tools exposed). CIM is useful when there is no dedicated cmdlet, or when you want consistent data across many Windows versions.
Beginner rule of thumb: use a dedicated cmdlet when it exists; use Get-CimInstance when you need hardware/OS inventory details that aren’t exposed by a single friendly cmdlet. In this chapter, all examples are safe, read-only queries.
Recipe set 1: OS details
Quick OS summary with Get-ComputerInfo
Get-ComputerInfo returns a large object with many properties. For a quick OS-focused view, select only what you need:
Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion, OsHardwareAbstractionLayer, OsBuildNumber, OsArchitectureStep-by-step:
Continue in our app.
You can listen to the audiobook with the screen off, receive a free certificate for this course, and also have access to 5,000 other free online courses.
Or continue reading below...Download the app
- Run the command as-is to see a compact summary.
- If you need more OS-related fields, run
Get-ComputerInfoalone and look for properties starting withOsorWindows.
OS details via CIM (works well for inventory)
Win32_OperatingSystem is a common CIM class for OS inventory. It’s handy when you want install date, last boot time, and version info in one place.
Get-CimInstance -ClassName Win32_OperatingSystem | Select-Object Caption, Version, BuildNumber, InstallDate, LastBootUpTimeTip: CIM date/time values may display in a long format; they are still real date objects you can compare and format later.
Recipe set 2: Computer name and uptime
Computer name
For a quick check:
$env:COMPUTERNAMEOr, if you want it as part of a richer system object:
Get-ComputerInfo | Select-Object CsNameUptime (how long since last boot)
A reliable approach is to read the last boot time from CIM and subtract it from the current time.
$os = Get-CimInstance -ClassName Win32_OperatingSystem $uptime = (Get-Date) - $os.LastBootUpTime $uptimeIf you want a cleaner display:
[pscustomobject]@{ LastBoot = $os.LastBootUpTime; UptimeDays = [math]::Round($uptime.TotalDays, 2) }Recipe set 3: Disk and memory info
Disk space (logical disks)
Use CIM to query logical disks and calculate free/used space. This is a classic inventory check.
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType=3" | Select-Object DeviceID, VolumeName, @{n='SizeGB';e={[math]::Round($_.Size/1GB,2)}}, @{n='FreeGB';e={[math]::Round($_.FreeSpace/1GB,2)}}, @{n='FreePct';e={[math]::Round(($_.FreeSpace/$_.Size)*100,1)}}Step-by-step:
DriveType=3limits results to local fixed disks (not CD/DVD or removable).- The calculated properties convert bytes to GB and compute a percentage.
Physical memory (RAM)
To see total installed memory:
Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object Name, @{n='TotalMemoryGB';e={[math]::Round($_.TotalPhysicalMemory/1GB,2)}}To see each memory module (useful for hardware inventory):
Get-CimInstance -ClassName Win32_PhysicalMemory | Select-Object BankLabel, Manufacturer, Capacity, SpeedIf you want capacity in GB per module:
Get-CimInstance -ClassName Win32_PhysicalMemory | Select-Object BankLabel, Manufacturer, @{n='CapacityGB';e={[math]::Round($_.Capacity/1GB,2)}}, SpeedRecipe set 4: Network configuration
High-level network view (recommended starting point)
Get-NetIPConfiguration provides a friendly summary of adapters, IP addresses, gateways, and DNS settings.
Get-NetIPConfigurationTo keep it concise:
Get-NetIPConfiguration | Select-Object InterfaceAlias, IPv4Address, IPv4DefaultGateway, DNSServerIP addresses only (quick check)
Get-NetIPAddress | Where-Object AddressFamily -eq IPv4 | Select-Object InterfaceAlias, IPAddress, PrefixLengthDNS client configuration
Get-DnsClientServerAddress | Select-Object InterfaceAlias, AddressFamily, ServerAddressesNetwork adapter status
Get-NetAdapter | Select-Object Name, Status, LinkSpeed, MacAddressBeginner note: if you see multiple adapters (Wi-Fi, Ethernet, virtual adapters), focus on the one that is Up and has a default gateway.
Recipe set 5: Event log queries (modern and fast)
Why Get-WinEvent (and when to use it)
Get-WinEvent is the modern cmdlet for reading Windows event logs. It supports filtering efficiently (especially with -FilterHashtable), which is important because logs can be large.
Get the newest errors from the System log
Get-WinEvent -LogName System -MaxEvents 20 | Where-Object LevelDisplayName -eq 'Error' | Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, MessageIf you want the newest 20 events regardless of level, remove the Where-Object filter.
Filter by time range (last 24 hours)
-FilterHashtable is a good habit for performance because it filters at the source.
$start = (Get-Date).AddHours(-24) Get-WinEvent -FilterHashtable @{ LogName='System'; StartTime=$start } | Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, MessageFilter by Event ID (example: unexpected shutdowns)
Event ID 6008 in the System log often indicates an unexpected shutdown. Querying it can help explain reboots.
Get-WinEvent -FilterHashtable @{ LogName='System'; Id=6008 } -MaxEvents 10 | Select-Object TimeCreated, Id, MessageApplication crashes (example pattern)
Application Error events commonly use ID 1000 in the Application log. This is a useful starting point when an app “just closes.”
Get-WinEvent -FilterHashtable @{ LogName='Application'; Id=1000 } -MaxEvents 10 | Select-Object TimeCreated, ProviderName, MessageSafety reminder: these commands only read logs. They do not clear or modify them.
Build a repeatable “system snapshot” for sharing
The goal is a concise, readable snapshot you can run on demand and export to a file. Keep it read-only and avoid collecting sensitive data unnecessarily. The following example gathers: OS summary, uptime, disk free space, memory total, basic network config, and a small slice of recent errors.
Step-by-step: create a snapshot object
Run this in PowerShell to build a single object that contains multiple sections:
$os = Get-CimInstance -ClassName Win32_OperatingSystem $cs = Get-CimInstance -ClassName Win32_ComputerSystem $uptime = (Get-Date) - $os.LastBootUpTime $disks = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType=3" | Select-Object DeviceID, @{n='SizeGB';e={[math]::Round($_.Size/1GB,2)}}, @{n='FreeGB';e={[math]::Round($_.FreeSpace/1GB,2)}}, @{n='FreePct';e={[math]::Round(($_.FreeSpace/$_.Size)*100,1)}} $net = Get-NetIPConfiguration | Select-Object InterfaceAlias, IPv4Address, IPv4DefaultGateway, DNSServer $start = (Get-Date).AddDays(-1) $recentSystemErrors = Get-WinEvent -FilterHashtable @{LogName='System'; StartTime=$start} -ErrorAction SilentlyContinue | Where-Object LevelDisplayName -eq 'Error' | Select-Object -First 10 TimeCreated, ProviderName, Id, Message $snapshot = [pscustomobject]@{ ComputerName = $cs.Name OS = $os.Caption OSVersion = $os.Version BuildNumber = $os.BuildNumber LastBoot = $os.LastBootUpTime UptimeDays = [math]::Round($uptime.TotalDays,2) TotalMemoryGB = [math]::Round($cs.TotalPhysicalMemory/1GB,2) Disks = $disks Network = $net RecentSystemErrors = $recentSystemErrors } $snapshotWhat to look for:
- UptimeDays helps correlate issues with recent reboots.
- FreePct highlights low disk space quickly.
- Network shows whether the machine has an IP and default gateway.
- RecentSystemErrors gives a small, relevant slice of log data without dumping everything.
Export the snapshot to a shareable file
Because the snapshot contains nested sections (disks, network, events), choose an export format that preserves structure.
Option A: JSON (good for structure and re-importing)
$path = "$env:USERPROFILE\Desktop\SystemSnapshot.json" $snapshot | ConvertTo-Json -Depth 5 | Set-Content -Path $path -Encoding UTF8Option B: Text report (easy to read in email/tickets)
$path = "$env:USERPROFILE\Desktop\SystemSnapshot.txt" $snapshot | Out-String | Set-Content -Path $path -Encoding UTF8Tip: JSON is better for preserving nested data; text is better for quick human reading.
Exercises (safe, read-only)
Exercise 1: OS + uptime mini-report
- Create variables for OS info and uptime using
Win32_OperatingSystem. - Output a
[pscustomobject]with: computer name, OS caption, version, last boot time, uptime in hours.
$os = Get-CimInstance Win32_OperatingSystem $uptime = (Get-Date) - $os.LastBootUpTime [pscustomobject]@{ ComputerName = $env:COMPUTERNAME OS = $os.Caption Version = $os.Version LastBoot = $os.LastBootUpTime UptimeHours = [math]::Round($uptime.TotalHours,1) }Exercise 2: Disk “low space” check
- Query fixed disks.
- Show only disks with less than 15% free space.
Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" | Where-Object { $_.Size -gt 0 -and (($_.FreeSpace/$_.Size)*100) -lt 15 } | Select-Object DeviceID, @{n='FreePct';e={[math]::Round(($_.FreeSpace/$_.Size)*100,1)}}, @{n='FreeGB';e={[math]::Round($_.FreeSpace/1GB,2)}}Exercise 3: Network snapshot for the active adapter
- List adapters that are up.
- For each, show IP and default gateway.
Get-NetAdapter | Where-Object Status -eq 'Up' | ForEach-Object { Get-NetIPConfiguration -InterfaceIndex $_.ifIndex } | Select-Object InterfaceAlias, IPv4Address, IPv4DefaultGateway, DNSServerExercise 4: Last day of System errors exported to a file
- Query System log errors from the last 24 hours.
- Export to a text file on the Desktop.
$start = (Get-Date).AddHours(-24) $events = Get-WinEvent -FilterHashtable @{LogName='System'; StartTime=$start} | Where-Object LevelDisplayName -eq 'Error' | Select-Object TimeCreated, ProviderName, Id, Message $path = "$env:USERPROFILE\Desktop\SystemErrors_Last24Hours.txt" $events | Format-Table -AutoSize | Out-String | Set-Content -Path $path -Encoding UTF8Exercise 5: One-command snapshot you can rerun
Create a single script block that generates the snapshot and writes it to JSON. Run it, then open the JSON file to confirm it contains disks, network, and recent errors.
$path = "$env:USERPROFILE\Desktop\SystemSnapshot.json" & { $os = Get-CimInstance Win32_OperatingSystem $cs = Get-CimInstance Win32_ComputerSystem $uptime = (Get-Date) - $os.LastBootUpTime [pscustomobject]@{ ComputerName = $cs.Name OS = $os.Caption Version = $os.Version Build = $os.BuildNumber LastBoot = $os.LastBootUpTime UptimeDays = [math]::Round($uptime.TotalDays,2) TotalMemoryGB = [math]::Round($cs.TotalPhysicalMemory/1GB,2) Disks = Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" | Select-Object DeviceID, @{n='SizeGB';e={[math]::Round($_.Size/1GB,2)}}, @{n='FreeGB';e={[math]::Round($_.FreeSpace/1GB,2)}}, @{n='FreePct';e={[math]::Round(($_.FreeSpace/$_.Size)*100,1)}} Network = Get-NetIPConfiguration | Select-Object InterfaceAlias, IPv4Address, IPv4DefaultGateway, DNSServer RecentSystemErrors = (Get-WinEvent -FilterHashtable @{LogName='System'; StartTime=(Get-Date).AddDays(-1)} | Where-Object LevelDisplayName -eq 'Error' | Select-Object -First 10 TimeCreated, ProviderName, Id, Message) } } | ConvertTo-Json -Depth 5 | Set-Content -Path $path -Encoding UTF8