Cross-Platform Hardware Inventory Scripting: Retrieving Manufacturer, Model & Serial Numbers via CLI


9 views

Maintaining accurate hardware records across mixed OS environments is painful when dealing with physical stickers. Here's how to extract critical identifiers programmatically:

For Windows systems (XP through Server 2008), WMI provides the most comprehensive access:

wmic bios get manufacturer,serialnumber
wmic csproduct get name,vendor,identifyingnumber
wmic baseboard get product,manufacturer,serialnumber

For structured output in PowerShell:

Get-WmiObject Win32_ComputerSystemProduct | Select-Object Vendor,Name,IdentifyingNumber
Get-WmiObject Win32_BIOS | Select-Object Manufacturer,SerialNumber

Most Linux distributions include dmidecode (run as root):

sudo dmidecode -t system | grep -E 'Manufacturer|Product Name|Serial Number'
sudo dmidecode -t baseboard | grep -E 'Manufacturer|Product Name|Serial Number'

For headless environments where dmidecode isn't available:

cat /sys/class/dmi/id/{sys_vendor,product_name,product_serial}

For environments mixing both OS families, this Python script handles both:

import platform
import subprocess

def get_hardware_info():
    system = platform.system()
    
    if system == "Windows":
        try:
            manufacturer = subprocess.check_output(
                "wmic csproduct get vendor", shell=True
            ).decode().split('\n')[1].strip()
            
            model = subprocess.check_output(
                "wmic csproduct get name", shell=True
            ).decode().split('\n')[1].strip()
            
            serial = subprocess.check_output(
                "wmic bios get serialnumber", shell=True
            ).decode().split('\n')[1].strip()
            
            return (manufacturer, model, serial)
            
        except Exception as e:
            print(f"Windows WMI query failed: {str(e)}")
            return (None, None, None)
            
    elif system == "Linux":
        try:
            vendor = subprocess.check_output(
                "cat /sys/class/dmi/id/sys_vendor", shell=True
            ).decode().strip()
            
            product = subprocess.check_output(
                "cat /sys/class/dmi/id/product_name", shell=True
            ).decode().strip()
            
            serial = subprocess.check_output(
                "cat /sys/class/dmi/id/product_serial", shell=True
            ).decode().strip()
            
            return (vendor, product, serial)
            
        except Exception as e:
            print(f"Linux DMI query failed: {str(e)}")
            return (None, None, None)
            
    else:
        return (None, None, None)

For mass inventory collection:

  • Package scripts as standalone executables using PyInstaller (Python) or compile to EXE (Windows batch)
  • Schedule execution via Group Policy (Windows) or Ansible (Linux)
  • Output to centralized SQL database using system-specific connectors

Common pitfalls to address:

# Virtual machines often return generic identifiers
# Check for hypervisor signatures:
wmic baseboard get product  # Returns "Virtual Machine" for Hyper-V
dmidecode -s system-manufacturer  # Returns "QEMU" for KVM

For systems where standard methods fail, consider:

# Windows fallback to registry
reg query "HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\BIOS"

# Linux alternative for ARM devices
cat /proc/device-tree/model

For enterprise inventory without third-party tools, we can leverage built-in OS capabilities. Windows provides WMI while Linux uses DMI through dmidecode. Here's how to implement a unified collection method:


# For Windows systems (works from XP onward):
$computerInfo = Get-WmiObject -Class Win32_ComputerSystemProduct | 
                Select-Object Vendor, Version, IdentifyingNumber
Write-Output "Manufacturer: $($computerInfo.Vendor)"
Write-Output "Model: $($computerInfo.Version)" 
Write-Output "Serial: $($computerInfo.IdentifyingNumber)"

# Alternative using WMIC (works on legacy systems):
wmic csproduct get vendor, name, identifyingnumber /format:csv

#!/bin/bash
# For Debian/Ubuntu/Fedora systems:
MANUFACTURER=$(sudo dmidecode -s system-manufacturer)
MODEL=$(sudo dmidecode -s system-product-name)
SERIAL=$(sudo dmidecode -s system-serial-number)

echo "Manufacturer: $MANUFACTURER"
echo "Model: $MODEL"
echo "Serial: $SERIAL"

# For systems without dmidecode:
cat /sys/class/dmi/id/{sys_vendor,product_name,product_serial} 2>/dev/null

import platform
import subprocess

def get_hardware_info():
    system = platform.system()
    
    if system == "Windows":
        cmd = 'wmic csproduct get vendor, name, identifyingnumber /format:csv'
        output = subprocess.check_output(cmd, shell=True).decode()
        _, vendor, name, serial = output.strip().split(',')
    else:
        try:
            vendor = subprocess.check_output(
                'sudo dmidecode -s system-manufacturer', 
                shell=True).decode().strip()
            name = subprocess.check_output(
                'sudo dmidecode -s system-product-name', 
                shell=True).decode().strip()
            serial = subprocess.check_output(
                'sudo dmidecode -s system-serial-number', 
                shell=True).decode().strip()
        except:
            with open('/sys/class/dmi/id/sys_vendor') as f:
                vendor = f.read().strip()
            with open('/sys/class/dmi/id/product_name') as f:
                name = f.read().strip()
            with open('/sys/class/dmi/id/product_serial') as f:
                serial = f.read().strip()
    
    return {
        'manufacturer': vendor,
        'model': name,
        'serial': serial
    }

For database integration, modify the output format accordingly:


# MySQL INSERT format
print(f"INSERT INTO inventory VALUES ('{vendor}', '{name}', '{serial}');")

# JSON output
import json
print(json.dumps(get_hardware_info(), indent=2))

For mass deployment across networks:

  • Use SSH (Linux) or WinRM (Windows) for remote execution
  • Schedule through cron (Linux) or Task Scheduler (Windows)
  • Output to centralized log file or database