# ============================================================
# PC / Laptop Audit Report
# Generates one clean HTML report on Desktop
# Includes:
# Brand / Model / Serial Number / CPU / RAM / Storage / Storage %
# GPU / Windows / BIOS / Battery Design Capacity / Battery Health
# ============================================================
$ReportTime = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$Desktop = [Environment]::GetFolderPath("Desktop")
$OutputFile = Join-Path $Desktop "PC-Audit-Report.html"
$OfficialBatteryReport = Join-Path $env:TEMP "official-battery-report.html"
function Get-SafeValue {
param(
$Value,
$Fallback = "N/A"
)
if ($null -eq $Value -or $Value -eq "") {
return $Fallback
}
return $Value
}
function Convert-ToHtmlSafe {
param($Value)
if ($null -eq $Value -or $Value -eq "") {
return "N/A"
}
$Text = [string]$Value
$Text = $Text -replace "&", "&"
$Text = $Text -replace "<", "<"
$Text = $Text -replace ">", ">"
$Text = $Text -replace '"', """
$Text = $Text -replace "'", "'"
return $Text
}
function Get-BatteryReportValue {
param(
[string]$HtmlContent,
[string]$Label
)
if ($null -eq $HtmlContent -or $HtmlContent -eq "") {
return "N/A"
}
$Pattern = "(?is)
]*>\s*(?:]*>)?\s*$Label\s*(?:)?\s* | \s*]*>\s*(.*?)\s* | "
if ($HtmlContent -match $Pattern) {
return ($matches[1] -replace "<.*?>", "").Trim()
}
return "N/A"
}
function Convert-CapacityToNumber {
param([string]$CapacityText)
if ($null -eq $CapacityText -or $CapacityText -eq "N/A") {
return $null
}
$NumberOnly = ($CapacityText -replace "[^\d]", "")
if ($NumberOnly) {
return [double]$NumberOnly
}
return $null
}
function Get-PercentUsed {
param(
[double]$Size,
[double]$FreeSpace
)
if ($Size -gt 0) {
$Used = $Size - $FreeSpace
return [math]::Round(($Used / $Size) * 100, 1)
}
return "N/A"
}
# ============================================================
# Generate official Windows battery report
# ============================================================
$BatteryReportContent = ""
try {
powercfg /batteryreport /output $OfficialBatteryReport | Out-Null
$BatteryReportContent = Get-Content $OfficialBatteryReport -Raw -ErrorAction SilentlyContinue
} catch {
$BatteryReportContent = ""
}
# ============================================================
# Basic system info
# ============================================================
$ComputerSystem = Get-CimInstance Win32_ComputerSystem -ErrorAction SilentlyContinue
$BIOS = Get-CimInstance Win32_BIOS -ErrorAction SilentlyContinue
$OS = Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue
$CPU = Get-CimInstance Win32_Processor -ErrorAction SilentlyContinue | Select-Object -First 1
$ComputerName = Get-SafeValue $env:COMPUTERNAME
$Manufacturer = Get-SafeValue $ComputerSystem.Manufacturer
$Model = Get-SafeValue $ComputerSystem.Model
$SerialNumber = Get-SafeValue $BIOS.SerialNumber
$CpuName = Get-SafeValue $CPU.Name
$CpuCores = Get-SafeValue $CPU.NumberOfCores
$CpuThreads = Get-SafeValue $CPU.NumberOfLogicalProcessors
$BiosDate = "N/A"
if ($BIOS.ReleaseDate) {
try {
$BiosDate = [Management.ManagementDateTimeConverter]::ToDateTime($BIOS.ReleaseDate).ToString("yyyy-MM-dd")
} catch {
$BiosDate = "N/A"
}
}
$BiosInfo = "$(Get-SafeValue $BIOS.SMBIOSBIOSVersion) / $BiosDate"
$WindowsInfo = "$(Get-SafeValue $OS.Caption) - Build $(Get-SafeValue $OS.BuildNumber) - $(Get-SafeValue $OS.OSArchitecture)"
$PlatformRole = switch ($ComputerSystem.PCSystemType) {
1 { "Desktop" }
2 { "Laptop / Mobile" }
3 { "Workstation" }
4 { "Enterprise Server" }
5 { "SOHO Server" }
6 { "Appliance PC" }
7 { "Performance Server" }
8 { "Maximum" }
default { "Unknown" }
}
# ============================================================
# RAM info
# ============================================================
$RamModules = Get-CimInstance Win32_PhysicalMemory -ErrorAction SilentlyContinue
if ($RamModules) {
$TotalRamGB = [math]::Round(($RamModules | Measure-Object -Property Capacity -Sum).Sum / 1GB, 1)
} else {
$TotalRamGB = "N/A"
}
$RamRows = ""
foreach ($Ram in $RamModules) {
$RamSizeGB = if ($Ram.Capacity) { [math]::Round($Ram.Capacity / 1GB, 1) } else { "N/A" }
$RamSpeed = Get-SafeValue $Ram.Speed
$RamManufacturer = Get-SafeValue $Ram.Manufacturer
$RamPartNumber = Get-SafeValue $Ram.PartNumber
$RamSlot = Get-SafeValue $Ram.DeviceLocator
$RamRows += "| $(Convert-ToHtmlSafe $RamSlot) | $RamSizeGB GB | $RamSpeed MHz | $(Convert-ToHtmlSafe $RamManufacturer) | $(Convert-ToHtmlSafe $RamPartNumber) |
`n"
}
if ($RamRows -eq "") {
$RamRows = "| N/A |
"
}
# ============================================================
# Physical storage info
# ============================================================
$DiskDrives = Get-CimInstance Win32_DiskDrive -ErrorAction SilentlyContinue
$DiskRows = ""
foreach ($Disk in $DiskDrives) {
$DiskModel = Get-SafeValue $Disk.Model
$DiskSizeGB = if ($Disk.Size) { [math]::Round($Disk.Size / 1GB, 1) } else { "N/A" }
$DiskType = Get-SafeValue $Disk.MediaType
$DiskInterface = Get-SafeValue $Disk.InterfaceType
$DiskSerial = Get-SafeValue $Disk.SerialNumber
$DiskRows += "| $(Convert-ToHtmlSafe $DiskModel) | $DiskSizeGB GB | $(Convert-ToHtmlSafe $DiskType) | $(Convert-ToHtmlSafe $DiskInterface) | $(Convert-ToHtmlSafe $DiskSerial) |
`n"
}
if ($DiskRows -eq "") {
$DiskRows = "| N/A |
"
}
# ============================================================
# Drive usage / storage percentage
# ============================================================
$LogicalDisks = Get-CimInstance Win32_LogicalDisk -Filter "DriveType=3" -ErrorAction SilentlyContinue
$DriveRows = ""
foreach ($Drive in $LogicalDisks) {
$DriveLetter = Get-SafeValue $Drive.DeviceID
$VolumeName = Get-SafeValue $Drive.VolumeName
$SizeGB = if ($Drive.Size) { [math]::Round($Drive.Size / 1GB, 1) } else { "N/A" }
$FreeGB = if ($Drive.FreeSpace) { [math]::Round($Drive.FreeSpace / 1GB, 1) } else { "N/A" }
$UsedPercent = if ($Drive.Size) { Get-PercentUsed -Size $Drive.Size -FreeSpace $Drive.FreeSpace } else { "N/A" }
$DriveRows += "| $(Convert-ToHtmlSafe $DriveLetter) | $(Convert-ToHtmlSafe $VolumeName) | $SizeGB GB | $FreeGB GB | $UsedPercent% |
`n"
}
if ($DriveRows -eq "") {
$DriveRows = "| N/A |
"
}
# ============================================================
# GPU info
# ============================================================
$GPUs = Get-CimInstance Win32_VideoController -ErrorAction SilentlyContinue
$GpuRows = ""
foreach ($GPU in $GPUs) {
$GpuName = Get-SafeValue $GPU.Name
$GpuRamGB = if ($GPU.AdapterRAM -and $GPU.AdapterRAM -gt 0) {
[math]::Round($GPU.AdapterRAM / 1GB, 1)
} else {
"N/A"
}
$GpuDriver = Get-SafeValue $GPU.DriverVersion
$GpuRows += "| $(Convert-ToHtmlSafe $GpuName) | $GpuRamGB GB | $(Convert-ToHtmlSafe $GpuDriver) |
`n"
}
if ($GpuRows -eq "") {
$GpuRows = "| No GPU information found |
"
}
# ============================================================
# Battery info
# ============================================================
$BatteryStatic = Get-CimInstance -Namespace root\wmi -ClassName BatteryStaticData -ErrorAction SilentlyContinue | Select-Object -First 1
$WinBattery = Get-CimInstance Win32_Battery -ErrorAction SilentlyContinue | Select-Object -First 1
$BatteryName = Get-SafeValue $WinBattery.Name
$BatteryManufacturer = Get-SafeValue $BatteryStatic.ManufactureName
$BatterySerial = Get-SafeValue $BatteryStatic.SerialNumber
$BatteryChemistry = Get-SafeValue $WinBattery.Chemistry
switch ($BatteryChemistry) {
2 { $BatteryChemistryText = "Unknown" }
3 { $BatteryChemistryText = "Lead Acid" }
4 { $BatteryChemistryText = "NiCd" }
5 { $BatteryChemistryText = "NiMH" }
6 { $BatteryChemistryText = "Li-ion" }
7 { $BatteryChemistryText = "Zinc Air" }
8 { $BatteryChemistryText = "Li-Polymer" }
default { $BatteryChemistryText = Get-SafeValue $BatteryChemistry }
}
$DesignCapacity = Get-BatteryReportValue $BatteryReportContent "DESIGN CAPACITY"
$FullChargeCapacity = Get-BatteryReportValue $BatteryReportContent "FULL CHARGE CAPACITY"
$CycleCount = Get-BatteryReportValue $BatteryReportContent "CYCLE COUNT"
$DesignNumber = Convert-CapacityToNumber $DesignCapacity
$FullNumber = Convert-CapacityToNumber $FullChargeCapacity
if ($DesignNumber -and $FullNumber -and $DesignNumber -gt 0) {
$BatteryHealth = [math]::Round(($FullNumber / $DesignNumber) * 100, 1)
$BatteryHealthText = "$BatteryHealth%"
} else {
$BatteryHealthText = "N/A"
}
# ============================================================
# HTML report
# ============================================================
$Html = @"
PC Audit Report
PC Audit Report
Generated on: $(Convert-ToHtmlSafe $ReportTime)
Basic Device Information
| Computer Name | $(Convert-ToHtmlSafe $ComputerName) |
| Manufacturer / Brand | $(Convert-ToHtmlSafe $Manufacturer) |
| Model | $(Convert-ToHtmlSafe $Model) |
| Serial Number | $(Convert-ToHtmlSafe $SerialNumber) |
| Platform Type | $(Convert-ToHtmlSafe $PlatformRole) |
| BIOS | $(Convert-ToHtmlSafe $BiosInfo) |
| Windows | $(Convert-ToHtmlSafe $WindowsInfo) |
CPU
| Processor | $(Convert-ToHtmlSafe $CpuName) |
| Cores | $(Convert-ToHtmlSafe $CpuCores) |
| Threads | $(Convert-ToHtmlSafe $CpuThreads) |
RAM
| Slot |
Capacity |
Speed |
Manufacturer |
Part Number |
$RamRows
Physical Storage
| Model |
Capacity |
Media Type |
Interface |
Serial Number |
$DiskRows
Drive Usage
| Drive |
Volume Name |
Total Capacity |
Free Space |
Used Percentage |
$DriveRows
GPU
| GPU Name |
GPU Memory |
Driver Version |
$GpuRows
Battery
| Battery Name | $(Convert-ToHtmlSafe $BatteryName) |
| Manufacturer | $(Convert-ToHtmlSafe $BatteryManufacturer) |
| Battery Serial Number | $(Convert-ToHtmlSafe $BatterySerial) |
| Chemistry | $(Convert-ToHtmlSafe $BatteryChemistryText) |
| Design Capacity | $(Convert-ToHtmlSafe $DesignCapacity) |
| Full Charge Capacity | $(Convert-ToHtmlSafe $FullChargeCapacity) |
| Battery Health | $(Convert-ToHtmlSafe $BatteryHealthText) |
| Cycle Count | $(Convert-ToHtmlSafe $CycleCount) |
Note: Some values may show as N/A depending on the device, Windows version, BIOS permission, or whether the device has a battery.
"@
# ============================================================
# Save report
# ============================================================
$Html | Out-File -FilePath $OutputFile -Encoding UTF8
# ============================================================
# Console output
# ============================================================
Write-Host ""
Write-Host "===== PC AUDIT REPORT GENERATED =====" -ForegroundColor Green
Write-Host "Saved to: $OutputFile" -ForegroundColor Yellow
Write-Host "Opening report now..." -ForegroundColor Cyan
Start-Process $OutputFile