How to Remotely Collect All Domain Computers Serial Numbers and Generate a Report On Windows Server 2025
Managing hardware inventory across an enterprise Active Directory environment is a critical task for IT administrators. One of the most important pieces of hardware information is the computer serial number, which is essential for warranty tracking, asset management, and compliance reporting. In this article, we’ll explore several methods to remotely collect serial numbers from all domain computers and generate comprehensive reports on Windows Server 2025.
Why Bother With Remote Collection?
Let me paint a picture: You’ve got 500 computers spread across multiple offices. Your boss just asked for a complete hardware inventory report by tomorrow morning. Walking around to each machine with a notepad? That’s not happening. Asking users to run commands and email you results? Good luck with that.
Remote serial number collection using PowerShell is the practical solution, allowing you to efficiently retrieve data from all domain-connected devices. The good news is that Windows Server 2025 comes with everything you need built right in.
Prerequisites
Before you begin, ensure you have:
- Administrative privileges on Windows Server 2025
- Active Directory Domain Services installed and configured
- PowerShell 5.1 or later (Windows Server 2025 includes PowerShell 7+)
- Network connectivity to target computers
- Appropriate firewall rules allowing WMI and PowerShell remoting
- Domain administrator credentials or equivalent permissions
Method 1: Using PowerShell with Get-ADComputer and WMI
This method combines Active Directory queries with Windows Management Instrumentation to retrieve serial numbers from all domain computers.
Step 1: Enable PowerShell Remoting
First, ensure PowerShell remoting is enabled on your target computers. You can enable it domain-wide using Group Policy:
- Open Group Policy Management Console
- Create or edit a GPO linked to your computers OU
- Navigate to: Computer Configuration > Policies > Administrative Templates > Windows Components > Windows PowerShell
- Enable “Turn on Script Execution” and set it to “Allow all scripts”
- Also enable PowerShell remoting via: Computer Configuration > Preferences > Control Panel Settings > Services
- Create a new service setting for “WinRM” and set it to Automatic start
Alternatively, run this command on each computer or via GPO startup script:
powershell
Enable-PSRemoting -Force
Step 2: Create the Serial Number Collection Script
Create a new PowerShell script named Get-DomainComputerSerials.ps1:
powershell
# Import Active Directory module
Import-Module ActiveDirectory
# Set output file path
$OutputPath = "C:\Reports\ComputerSerialNumbers_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
$ErrorLogPath = "C:\Reports\ErrorLog_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
# Create Reports directory if it doesn't exist
New-Item -ItemType Directory -Path "C:\Reports" -Force | Out-Null
# Get all computer objects from Active Directory
Write-Host "Retrieving computer accounts from Active Directory..." -ForegroundColor Cyan
$Computers = Get-ADComputer -Filter {Enabled -eq $true} -Properties Name, OperatingSystem, LastLogonDate
# Initialize results array
$Results = @()
# Counter for progress
$Counter = 0
$TotalComputers = $Computers.Count
Write-Host "Found $TotalComputers enabled computer accounts. Starting serial number collection..." -ForegroundColor Green
# Loop through each computer
foreach ($Computer in $Computers) {
$Counter++
$PercentComplete = [math]::Round(($Counter / $TotalComputers) * 100, 2)
Write-Progress -Activity "Collecting Serial Numbers" -Status "Processing $($Computer.Name) ($Counter of $TotalComputers)" -PercentComplete $PercentComplete
$ComputerName = $Computer.Name
$SerialNumber = "N/A"
$Manufacturer = "N/A"
$Model = "N/A"
$Status = "Offline"
# Test if computer is online
if (Test-Connection -ComputerName $ComputerName -Count 1 -Quiet -ErrorAction SilentlyContinue) {
try {
# Get BIOS information including serial number
$BIOS = Get-WmiObject -Class Win32_BIOS -ComputerName $ComputerName -ErrorAction Stop
$ComputerSystem = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $ComputerName -ErrorAction Stop
$SerialNumber = $BIOS.SerialNumber
$Manufacturer = $ComputerSystem.Manufacturer
$Model = $ComputerSystem.Model
$Status = "Success"
} catch {
$Status = "Error: $($_.Exception.Message)"
Add-Content -Path $ErrorLogPath -Value "$(Get-Date) - $ComputerName - $($_.Exception.Message)"
}
} else {
$Status = "Offline/Unreachable"
}
# Create custom object with results
$Result = [PSCustomObject]@{
ComputerName = $ComputerName
SerialNumber = $SerialNumber
Manufacturer = $Manufacturer
Model = $Model
OperatingSystem = $Computer.OperatingSystem
LastLogon = $Computer.LastLogonDate
Status = $Status
CollectionDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
$Results += $Result
}
# Export results to CSV
Write-Host "`nExporting results to CSV..." -ForegroundColor Cyan
$Results | Export-Csv -Path $OutputPath -NoTypeInformation -Encoding UTF8
# Display summary
$SuccessCount = ($Results | Where-Object {$_.Status -eq "Success"}).Count
$OfflineCount = ($Results | Where-Object {$_.Status -like "Offline*"}).Count
$ErrorCount = ($Results | Where-Object {$_.Status -like "Error*"}).Count
Write-Host "`n=== Collection Summary ===" -ForegroundColor Green
Write-Host "Total Computers: $TotalComputers"
Write-Host "Successfully Collected: $SuccessCount" -ForegroundColor Green
Write-Host "Offline/Unreachable: $OfflineCount" -ForegroundColor Yellow
Write-Host "Errors: $ErrorCount" -ForegroundColor Red
Write-Host "`nReport saved to: $OutputPath" -ForegroundColor Cyan
if ($ErrorCount -gt 0) {
Write-Host "Error log saved to: $ErrorLogPath" -ForegroundColor Yellow
}
Step 3: Run the Script
Execute the script with administrative privileges:
powershell
.\Get-DomainComputerSerials.ps1
The script will generate a CSV report in C:\Reports\ with all collected information.
Method 2: Using PowerShell Remoting with Invoke-Command
This method uses PowerShell remoting for potentially faster collection from multiple computers simultaneously.
powershell
# Import Active Directory module
Import-Module ActiveDirectory
# Set output file
$OutputPath = "C:\Reports\SerialNumbers_Remote_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
# Get all enabled computers
$Computers = Get-ADComputer -Filter {Enabled -eq $true} | Select-Object -ExpandProperty Name
# Script block to run on remote computers
$ScriptBlock = {
$BIOS = Get-WmiObject -Class Win32_BIOS
$ComputerSystem = Get-WmiObject -Class Win32_ComputerSystem
[PSCustomObject]@{
ComputerName = $env:COMPUTERNAME
SerialNumber = $BIOS.SerialNumber
Manufacturer = $ComputerSystem.Manufacturer
Model = $ComputerSystem.Model
BIOSVersion = $BIOS.SMBIOSBIOSVersion
}
}
# Collect data from all computers in parallel
Write-Host "Collecting serial numbers from $($Computers.Count) computers..." -ForegroundColor Cyan
$Results = Invoke-Command -ComputerName $Computers -ScriptBlock $ScriptBlock -ErrorAction SilentlyContinue -ThrottleLimit 50 |
Select-Object ComputerName, SerialNumber, Manufacturer, Model, BIOSVersion
# Export to CSV
$Results | Export-Csv -Path $OutputPath -NoTypeInformation
Write-Host "Report generated: $OutputPath" -ForegroundColor Green
Write-Host "Total records collected: $($Results.Count)" -ForegroundColor Cyan
Method 3: Using CIM Instead of WMI (Recommended for Server 2025)
CIM (Common Information Model) is the modern replacement for WMI and offers better performance and reliability.
powershell
# Import Active Directory module
Import-Module ActiveDirectory
# Configuration
$OutputPath = "C:\Reports\SerialNumbers_CIM_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
$Computers = Get-ADComputer -Filter {Enabled -eq $true} -Properties Name, OperatingSystem
$Results = foreach ($Computer in $Computers) {
Write-Host "Processing: $($Computer.Name)" -ForegroundColor Yellow
try {
$CIMSession = New-CimSession -ComputerName $Computer.Name -ErrorAction Stop
$BIOS = Get-CimInstance -ClassName Win32_BIOS -CimSession $CIMSession
$CS = Get-CimInstance -ClassName Win32_ComputerSystem -CimSession $CIMSession
[PSCustomObject]@{
ComputerName = $Computer.Name
SerialNumber = $BIOS.SerialNumber
Manufacturer = $CS.Manufacturer
Model = $CS.Model
OperatingSystem = $Computer.OperatingSystem
Status = "Success"
}
Remove-CimSession -CimSession $CIMSession
} catch {
[PSCustomObject]@{
ComputerName = $Computer.Name
SerialNumber = "N/A"
Manufacturer = "N/A"
Model = "N/A"
OperatingSystem = $Computer.OperatingSystem
Status = "Failed: $($_.Exception.Message)"
}
}
}
$Results | Export-Csv -Path $OutputPath -NoTypeInformation
Write-Host "`nReport saved: $OutputPath" -ForegroundColor Green
Method 4: Creating an HTML Report with Enhanced Formatting
For a more visually appealing report that can be shared with management, create an HTML version:
powershell
# Collect data (using any of the methods above)
Import-Module ActiveDirectory
$Computers = Get-ADComputer -Filter {Enabled -eq $true} -Properties Name, OperatingSystem
$Results = foreach ($Computer in $Computers) {
if (Test-Connection -ComputerName $Computer.Name -Count 1 -Quiet) {
try {
$BIOS = Get-CimInstance -ClassName Win32_BIOS -ComputerName $Computer.Name -ErrorAction Stop
$CS = Get-CimInstance -ClassName Win32_ComputerSystem -ComputerName $Computer.Name -ErrorAction Stop
[PSCustomObject]@{
ComputerName = $Computer.Name
SerialNumber = $BIOS.SerialNumber
Manufacturer = $CS.Manufacturer
Model = $CS.Model
OS = $Computer.OperatingSystem
Status = '<span style="color:green">Online</span>'
}
} catch {
[PSCustomObject]@{
ComputerName = $Computer.Name
SerialNumber = "Error"
Manufacturer = "N/A"
Model = "N/A"
OS = $Computer.OperatingSystem
Status = '<span style="color:red">Error</span>'
}
}
} else {
[PSCustomObject]@{
ComputerName = $Computer.Name
SerialNumber = "Offline"
Manufacturer = "N/A"
Model = "N/A"
OS = $Computer.OperatingSystem
Status = '<span style="color:orange">Offline</span>'
}
}
}
# HTML styling
$HTMLHeader = @"
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1 { color: #0078D4; }
table { border-collapse: collapse; width: 100%; margin-top: 20px; }
th { background-color: #0078D4; color: white; padding: 12px; text-align: left; }
td { border: 1px solid #ddd; padding: 10px; }
tr:nth-child(even) { background-color: #f2f2f2; }
.summary { background-color: #e7f3ff; padding: 15px; border-radius: 5px; margin-bottom: 20px; }
</style>
"@
$HTMLReport = $Results | ConvertTo-Html -Head $HTMLHeader -PreContent "<h1>Domain Computer Serial Number Report</h1><div class='summary'><strong>Generated:</strong> $(Get-Date)<br><strong>Total Computers:</strong> $($Results.Count)</div>" -PostContent "<p><em>Report generated by Windows Server 2025</em></p>"
$HTMLPath = "C:\Reports\SerialNumbers_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"
$HTMLReport | Out-File -FilePath $HTMLPath
Write-Host "HTML Report generated: $HTMLPath" -ForegroundColor Green
Scheduling Automated Collection
To automatically collect serial numbers on a regular basis, create a scheduled task:
powershell
# Create a scheduled task to run weekly
$Action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-ExecutionPolicy Bypass -File C:\Scripts\Get-DomainComputerSerials.ps1"
$Trigger = New-ScheduledTaskTrigger -Weekly -DaysOfWeek Monday -At 2am
$Principal = New-ScheduledTaskPrincipal -UserId "DOMAIN\Administrator" -LogonType Password -RunLevel Highest
Register-ScheduledTask -TaskName "Weekly Serial Number Collection" -Action $Action -Trigger $Trigger -Principal $Principal -Description "Collects serial numbers from all domain computers weekly"
- Use
-ThrottleLimitparameter withInvoke-Commandto process multiple computers simultaneously - Filter only active computers using LastLogonDate property
- Consider collecting during off-hours
Conclusion
Collecting serial numbers from domain computers on Windows Server 2025 is straightforward using PowerShell and can be accomplished through multiple methods. The CIM-based approach is recommended for modern environments due to its improved performance and reliability. Whether you choose WMI, CIM, or PowerShell remoting, the key is to implement proper error handling, schedule regular collections, and maintain accurate inventory records for effective asset management.
By implementing one of these solutions, you’ll have an automated, reliable system for tracking hardware serial numbers across your entire domain infrastructure.


