WMI
The Ultimate Server Audit: Deep-Dive Inventory to Excel (VBScript) | Lazy Admin Blog

If you are facing a massive compliance audit or a data center migration, “basic” info isn’t enough. You need to know exactly what is under the hood: What roles are active? How much disk space is actually left? What random software was installed three years ago?
This VBScript is a one-stop-shop. It checks network connectivity and then scrapes WMI and the Registry to build a massive, multi-column Excel report.
What this Script Collects:
- Hardware: Manufacturer, Model, CPU Type, and RAM (converted to GB).
- OS Details: Version, Caption, and the exact Installation Date.
- Storage: Total Size vs. Free Space (with a Red-Alert highlight if space is < 20%).
- Network: DHCP status, IP, Subnet, and Gateway.
- Software & Roles: Every Windows Server Role/Feature and every application listed in the Registry’s Uninstall key (including version and install date).
Preparation
- Directory: Create
C:\Tempon your local machine. - Input: Create a file named
ServerList.txtinC:\Tempwith your server names (one per line). - Excel: Ensure Microsoft Excel is installed.
The Script: Server_Inventory.vbs
' Save as Server_Inventory.vbs in C:\Temp' lazyadminblog.com - Ultimate Inventory ScriptOn Error Resume Next dtmDate = DatestrMonth = Month(Date)strDay = Day(Date)strYear = Right(Year(Date),2)strFileName = "C:\Temp\ServerInventory_" & strMonth & "-" & strDay & "-" & strYear & ".xls"Set objExcel = CreateObject("Excel.Application") objExcel.Visible = True objExcel.Workbooks.Add Set fso1 = CreateObject("Scripting.FileSystemObject") Set pcfile = fso1.OpenTextFile("C:\Temp\ServerList.txt",1) Wscript.Echo "Audit in progress... Please wait!"'--- Setup Header Row ---Sub SetupHeader(col, text) objExcel.Cells(1, col).Value = text objExcel.Cells(1, col).Font.Colorindex = 2 objExcel.Cells(1, col).Font.Bold = True objExcel.Cells(1, col).Interior.ColorIndex = 23 objExcel.Cells(1, col).Alignment = -4108 ' CenterEnd SubSetupHeader 1, "Computer Name"SetupHeader 2, "Manufacturer"SetupHeader 3, "Model"SetupHeader 4, "RAM (GB)"SetupHeader 5, "Operating System"SetupHeader 6, "Installed Date"SetupHeader 7, "Processor"SetupHeader 8, "Drive"SetupHeader 9, "Drive Size (GB)"SetupHeader 10, "Free Space (GB)"SetupHeader 11, "Adapter Description"SetupHeader 12, "DHCP Enabled"SetupHeader 13, "IP Address"SetupHeader 14, "Subnet"SetupHeader 15, "Gateway"SetupHeader 16, "Roles & Features"SetupHeader 17, "Installed Software"SetupHeader 18, "Install Date"SetupHeader 19, "Version"SetupHeader 20, "Size"y = 2 Do While Not pcfile.AtEndOfStream computerName = pcfile.ReadLine Err.Clear Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & computerName & "\root\cimv2") If Err.Number = 0 Then ' Fetch Queries Set colSettings = objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem") Set colOSSettings = objWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem") Set colProcSettings = objWMIService.ExecQuery("SELECT * FROM Win32_Processor") Set colDiskSettings = objWMIService.ExecQuery("Select * from Win32_LogicalDisk Where DriveType=3") Set colAdapters = objWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True") For Each objComputer In colSettings strManufacturer = objComputer.Manufacturer strModel = objComputer.Model strRAM = FormatNumber((objComputer.TotalPhysicalMemory / (1024^3)), 2) For Each objOS In colOSSettings strOS = objOS.Caption OSinstDate = CDate(Mid(objOS.InstallDate,1,4)+"/"+Mid(objOS.InstallDate,5,2)+"/"+Mid(objOS.InstallDate,7,2)) For Each objProc In colProcSettings strProc = objProc.Name ' Populate Static Info objExcel.Cells(y, 1).Value = computerName objExcel.Cells(y, 2).Value = strManufacturer objExcel.Cells(y, 3).Value = strModel objExcel.Cells(y, 4).Value = strRAM objExcel.Cells(y, 5).Value = strOS objExcel.Cells(y, 6).Value = OSinstDate objExcel.Cells(y, 7).Value = strProc ' Drive Logic a = y For Each objDisk In colDiskSettings objExcel.Cells(a, 8).Value = objDisk.DeviceID sz = objDisk.Size / (1024^3) fr = objDisk.FreeSpace / (1024^3) objExcel.Cells(a, 9).Value = FormatNumber(sz, 2) objExcel.Cells(a, 10).Value = FormatNumber(fr, 2) If fr < (sz * 0.2) Then objExcel.Cells(a, 10).Interior.ColorIndex = 3 ' Low Space Alert a = a + 1 Next ' Network Logic b = y For Each objAdapter In colAdapters objExcel.Cells(b, 11).Value = objAdapter.Description objExcel.Cells(b, 12).Value = objAdapter.DHCPEnabled If Not IsNull(objAdapter.IPAddress) Then objExcel.Cells(b, 13).Value = objAdapter.IPAddress(0) If Not IsNull(objAdapter.IPSubnet) Then objExcel.Cells(b, 14).Value = objAdapter.IPSubnet(0) If Not IsNull(objAdapter.DefaultIPGateway) Then objExcel.Cells(b, 15).Value = objAdapter.DefaultIPGateway(0) b = b + 1 Next ' Roles & Features x = y Set colRoleFeatures = objWMIService.ExecQuery("Select * from Win32_ServerFeature") If colRoleFeatures.Count > 0 Then For Each objRole In colRoleFeatures objExcel.Cells(x, 16).Value = objRole.Name x = x + 1 Next Else objExcel.Cells(x, 16).Value = "None Found" End If ' Software Registry Scan s = y Const HKLM = &H80000002 strKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" Set objReg = GetObject("winmgmts://" & computerName & "/root/default:StdRegProv") objReg.EnumKey HKLM, strKey, arrSubkeys For Each strSubkey In arrSubkeys objReg.GetStringValue HKLM, strKey & strSubkey, "DisplayName", strVal1 If strVal1 <> "" Then objExcel.Cells(s, 17).Value = strVal1 objReg.GetStringValue HKLM, strKey & strSubkey, "InstallDate", strVal2 objExcel.Cells(s, 18).Value = strVal2 objReg.GetDWORDValue HKLM, strKey & strSubkey, "VersionMajor", vMaj objReg.GetDWORDValue HKLM, strKey & strSubkey, "VersionMinor", vMin objExcel.Cells(s, 19).Value = vMaj & "." & vMin s = s + 1 End If Next ' Advance Row to next available empty spot y = a If b > y Then y = b If x > y Then y = x If s > y Then y = s y = y + 1 ' Buffer line Next Next Next Else objExcel.Cells(y, 1).Value = computerName objExcel.Cells(y, 2).Value = "OFFLINE" objExcel.Cells(y, 2).Interior.ColorIndex = 3 y = y + 1 End If Loop ' Final FormattingFor col = 1 To 20: objExcel.Columns(col).AutoFit: NextobjExcel.ActiveWorkbook.SaveAs strFileNameWscript.Echo "Complete! Report saved to " & strFileName
Why it’s a Game Changer
- The “Red Flag” Feature: It automatically highlights any disk with less than 20% free space in Red. This instantly tells you which servers need urgent cleanup.
- Software Archeology: Most scripts skip software lists because they are messy. This script pulls directly from the
Uninstallregistry keys, capturing even the apps that don’t show up in standard WMI queries. - Intelligent Row Management: Because software, roles, and disks all have different counts, the script calculates the “max row” used for each server and jumps to the next clear space for the next machine.
Stop Hunting for Web Servers: How to Auto-Discover Every IIS Instance in Your Domain | Lazy Admin Blog

Have you ever been asked for a list of every active web server in your environment, only to realize your documentation is six months out of date? You could check your DNS records manually, or you could let PowerShell do the detective work for you.
This script scans your Active Directory for Windows Servers, checks if the World Wide Web Publishing Service (W3SVC) is actually running, and then pulls a deep-profile of the hardware, OS, and network configuration for every active hit.
The Setup
- Create the workspace: Create a folder at
C:\Temp\ServersRunningIIS. - Prepare the list: The script will automatically generate a list of all Windows Servers from AD, but ensure you have the Active Directory PowerShell module installed.
- Run with Privileges: Since the script uses WMI to query remote system info (RAM, OS Version, etc.), run your PowerShell ISE or Console as a Domain Admin.
The PowerShell Script
# Script: IIS Server Discovery & Profiler# Location: lazyadminblog.com# Purpose: Identify active IIS nodes and collect hardware/OS specsImport-Module ActiveDirectory# 1. Harvest all Windows Servers from ADWrite-Host "Gathering server list from Active Directory..." -ForegroundColor Cyan$servers = Get-ADComputer -Filter {operatingsystem -Like "Windows server*"} | Select-Object -ExpandProperty Name$servers | Out-File "C:\Temp\ServersRunningIIS\serverlist.txt"# 2. Load the list for processing$serversall = Get-Content "C:\Temp\ServersRunningIIS\serverlist.txt" Start-Transcript -Path "C:\Temp\ServersRunningIIS\log_output.txt" -Appendforeach($vm in $serversall) { try { # Check if IIS Service (W3SVC) exists and is running $iis = Get-WmiObject Win32_Service -ComputerName $vm -Filter "name='W3SVC'" -ErrorAction SilentlyContinue if($iis.State -eq "Running") { Write-Host "FOUND: IIS is active on $vm" -BackgroundColor DarkBlue -ForegroundColor DarkYellow # Collect Network Info $ipinfo = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $vm | Where-Object {$_.IPEnabled -eq $true -and $_.IPAddress -like "1*"} | Select-Object -First 1 # Collect Hardware Info $hwinfo = Get-WmiObject Win32_Computersystem -ComputerName $vm # Collect OS Info $osinfo = Get-WmiObject Win32_OperatingSystem -ComputerName $vm # Flattening data for CSV-style output $allinfo = "$($hwinfo.Name);$($hwinfo.Domain);$($ipinfo.IPAddress);$($ipinfo.IPSubnet);$($ipinfo.DefaultIPGateway);$($hwinfo.TotalPhysicalMemory);$($hwinfo.Manufacturer);$($hwinfo.Model);$($osinfo.Caption);$($osinfo.OSArchitecture);$($osinfo.ServicePackMajorVersion);$($osinfo.SystemDrive);$($osinfo.Version)" # Save results to our 'Running' list $allinfo | Out-File "C:\Temp\ServersRunningIIS\RunningWebServers.txt" -Append } } catch { Write-Host "Could not connect to $vm" -ForegroundColor Red }}Stop-TranscriptWrite-Host "Audit Complete! Check C:\Temp\ServersRunningIIS\RunningWebServers.txt" -ForegroundColor Green
What’s inside the report?
The output file (RunningWebServers.txt) uses a semicolon (;) delimiter, making it easy to import into Excel. It captures:
- Network: IP Address, Subnet, and Gateway.
- Hardware: Manufacturer, Model, RAM, and Domain membership.
- Software: OS Version, Architecture (x64/x86), and System Drive.
Lazy Admin Tip
If you want to open the results immediately in Excel, just rename the output file from .txt to .csv and use the “Text to Columns” feature in Excel with the semicolon as the separator!
From Zero to Complete IP Inventory in 5 Seconds: The Multi-Host VBScript | Lazy Admin Blog

Manually documenting IP addresses, MACs, and DNS settings is the definition of “busy work.” This VBScript automates the entire process. It reads a list of servers from a text file, queries each one via WMI, and builds a professional Excel report in real-time.
How to Use This Script
- Prepare the Input: Create a text file (e.g.,
servers.txt) and list your hostnames or IP addresses, one per line. - Save the Script: Save the code below as
IPAddressInventory.vbs. - Run: Double-click the
.vbsfile. When prompted, provide the full path to your text file (e.g.,C:\Scripts\servers.txt). - Requirement: You must have Microsoft Excel installed on the machine where you run the script.
The VBScript Code
VBScript
' Save as IPAddressInventory.vbs' Input: Text file with Hostnames/IPs' Output: Excel Spreadsheet (IP_Addresses.xlsx)On Error Resume NextConst FOR_READING = 1'--- File Input ---strSrvListFile = InputBox ("Please enter the server list file path OR UNC file path" & vbCrLf & "Eg: C:\Scripts\server.txt" & vbCrLf & "Eg: \\servername\scripts\server.txt","File Input location")Set objFSO = CreateObject ("Scripting.FileSystemObject")Set objReadFile = objFSO.OpenTextFile (strSrvListFile, FOR_READING)'--- File Output ---strOutput = objfso.GetParentFolderName(strSrvListFile) &"\"'--- Error Handling ---If Err.Number <> 0 Then WScript.Echo "Please Enter a Valid file Name" Err.Clear WScript.QuitEnd If'--- Excel Object Creation ---Set objExcel = CreateObject ("Excel.application")objExcel.Visible = TrueSet objWorkbook = objExcel.Workbooks.Add()Set objWorksheet = objWorkbook.Worksheets("Sheet1")x = 1y = 1'--- Define Headers ---objWorksheet.Cells (x, y).value = "S.No"objWorksheet.Cells (x, y+1).value = "Server Name"objWorksheet.Cells (x, y+2).value = "Description"objWorksheet.Cells (x, y+3).value = "IP_Address"objWorksheet.Cells (x, y+4).value = "Subnet"objWorksheet.Cells (x, y+5).value = "MACAddress"objWorksheet.Cells (x, y+6).value = "Gateway" objWorksheet.Cells (x, y+7).value = "Preffered DNS"objWorksheet.Cells (x, y+8).value = "Primary DNS"objWorksheet.Cells (x, y+9).value = "Secondary DNS"objWorksheet.Cells (x, y+10).value = "Additional DNS 1"objWorksheet.Cells (x, y+11).value = "Additional DNS 2"objWorksheet.Cells (x, y+12).value = "WINS Primary"objWorksheet.Cells (x, y+13).value = "WINS Secondary"objWorksheet.Cells (x, y+14).value = "DNS Suffix"objWorksheet.Cells (x, y+15).value = "DNS Suffix Order"objWorksheet.Cells (x, y+16).value = "Remarks"s = 1Do Until objReadFile.AtEndOfStream k = 0 arrComputer = objReadFile.ReadLine strServer = Split (arrComputer, ",") objWorksheet.Cells (x+1, y).value = s objWorksheet.Cells (x+1, y+1).value = strServer(k) Set objWMIService = GetObject ("winmgmts:" & "!\\" & strServer(k) & "\root\cimv2") '--- Query Network Information --- If Err.Number = 0 Then WScript.Echo strServer(k) &": Inventoring" Set colAdapters = objWMIService.ExecQuery("Select * from Win32_NetworkAdapterConfiguration Where IPEnabled = True") For Each objAdapter in colAdapters objWorksheet.Cells(x+1, y+2).Value = objAdapter.Description ' IP Address Logic If Not IsNull(objAdapter.IPAddress) Then For i = LBound(objAdapter.IPAddress) To UBound(objAdapter.IPAddress) If Not InStr(objAdapter.IPAddress(i),":") > "0" Then objWorksheet.Cells(x+1, y+3).Value = objAdapter.IPAddress(i) End If Next End If ' Subnet Logic If Not IsNull(objAdapter.IPSubnet) Then For i = LBound(objAdapter.IPSubnet) To UBound(objAdapter.IPSubnet) If objAdapter.IPSubnet(i)<> "64" Then objWorksheet.Cells(x+1, y+4).Value = objAdapter.IPSubnet(i) End If Next End If objWorksheet.Cells(x+1, y+5).Value = objAdapter.MACAddress ' Gateway Logic If IsNull(objAdapter.DefaultIPGateway) Then objWorksheet.Cells(x+1, y+6).Value = "Gateway Not Set" Else For i = LBound(objAdapter.DefaultIPGateway) To UBound(objAdapter.DefaultIPGateway) objWorksheet.Cells(x+1, y+6).Value = objAdapter.DefaultIPGateway(i) Next End If ' DNS Logic If IsNull(objAdapter.DNSServerSearchOrder) Then objworksheet.Cells(x+1, y+7).Value = "DNS Not Set" Else For i = LBound(objAdapter.DNSServerSearchOrder) To UBound(objAdapter.DNSServerSearchOrder) objWorksheet.Cells(x+1, y+7).Value = objAdapter.DNSServerSearchOrder(i) y = y + 1 Next End If y = 1 objWorksheet.Cells(x+1, y+12).Value = objAdapter.WINSPrimaryServer objWorksheet.Cells(x+1, y+13).Value = objAdapter.WINSSecondaryServer objWorksheet.Cells(x+1, y+14).Value = objAdapter.DNSDomain ' Suffix Logic If IsNull(objAdapter.DNSDomainSuffixSearchOrder) Then objworksheet.Cells(x+1, y+14).Value = "Suffix Order NA" Else For i = LBound(objAdapter.DNSDomainSuffixSearchOrder) To UBound(objAdapter.DNSDomainSuffixSearchOrder) objWorksheet.Cells(x+1, y+15).Value = objAdapter.DNSDomainSuffixSearchOrder(i) x = x + 1 Next x = x - 1 End If x = x + 1 WScript.Echo strServer(k) &": Completed" Next Else ' Error Handling for Offline Servers objWorksheet.Cells(x+1, y+16).Value = Err.Number & "_" & Err.Description WScript.Echo strServer(k) &": "& Err.Description Err.Clear x = x + 1 End If s = s + 1Loop'--- Formatting and Saving ---Set objRange = objWorksheet.UsedRangeobjRange.EntireColumn.Autofit()objExcel.ActiveWorkbook.Saveas strOutput & "IP_Addresses.xlsx"MsgBox "Operation Completed Successfully " ,,"IP Address"
Key Features of the Script
- Automatic Excel Formatting: It uses
UsedRange.Autofit()to ensure the data is readable as soon as the file opens. - WMI Integration: It queries the
Win32_NetworkAdapterConfigurationclass directly from the remote machine. - Multi-Adapter Support: If a server has multiple enabled NICs, the script loops through each to capture all configurations.
- Remark Logging: If a machine is unreachable, the error code and description are written directly into the Excel “Remarks” column so you know which servers to check manually.

How to Get Hardware Serial Numbers Remotely (WMIC & PowerShell)

As a SysAdmin, you often need a serial number or UUID for a warranty check or asset tracking. Instead of walking to the user’s desk or remoting into their session, you can pull this data directly from your workstation using these simple commands.
1. Using WMIC (Legacy Command Line)
WMIC is incredibly efficient for quick, one-off queries against remote systems.
To get a remote serial number:
DOS
wmic /node:"RemoteComputerName" bios get serialnumber
To export results to a central text file: If you are auditing multiple machines, use the /append switch to create a running list:
DOS
set myfile=\\Server\Share\Inventory.txtwmic /append:%myfile% /node:"RemoteComputerName" bios get serialnumber
2. Using PowerShell (Modern Method)
PowerShell is the preferred method for modern Windows environments (Windows 10/11 and Server 2016+). It returns objects that are much easier to manipulate.
Standard Command:
PowerShell
Get-WmiObject -ComputerName "RemoteComputerName" -Class Win32_BIOS
The “Lazy” Short Version:
PowerShell
gwmi -comp "RemoteComputerName" -cl win32_bios
3. Bonus Hardware Commands
Sometimes the serial number isn’t enough. Use these WMIC commands to get a deeper look at the hardware specs:
- CPU Details: Get the exact model and clock speeds.
wmic cpu get name, CurrentClockSpeed, MaxClockSpeed - System Product Info: Pull the motherboard name and the system’s unique UUID.
wmic csproduct get name, identifyingnumber, uuid - Full BIOS Audit: Get the BIOS name, version, and serial number in one go.
wmic bios get name, serialnumber, version
Troubleshooting Connectivity
If these commands fail with “Access Denied” or “RPC Server Unavailable,” check the following:
- Admin Rights: Your shell must be running with Domain Admin or local administrator permissions on the target.
- Firewall: Ensure “Windows Management Instrumentation (WMI)” is allowed through the Windows Firewall on the remote machine.
- WMI Service: Ensure the WinMgmt service is running on the target.
#SysAdmin #PowerShell #WMIC #WindowsServer #ITPro #TechTips #InventoryManagement #LazyAdmin #RemoteAdmin #HardwareHack