Public/Get-CpuInfo.ps1

function Get-CpuInfo {
    <#
    .SYNOPSIS
        Returns CPU information as a PSCustomObject.
    .DESCRIPTION
        Collects CPU name, physical cores, logical processors, and current usage percent.
        Works cross-platform. Pipe to ConvertTo-Json for JSON output.
    .EXAMPLE
        Get-CpuInfo
        Get-CpuInfo | ConvertTo-Json
    #>

    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param()

    $platform = Get-PlatformType

    switch ($platform) {
        'Windows' {
            $cpu = Get-CimInstance -ClassName Win32_Processor | Select-Object -First 1
            $usage = ($cpu.LoadPercentage) ?? 0
            [PSCustomObject]@{
                Name              = $cpu.Name.Trim()
                PhysicalCores     = $cpu.NumberOfCores
                LogicalProcessors = $cpu.NumberOfLogicalProcessors
                MaxClockSpeedMHz  = $cpu.MaxClockSpeed
                UsagePercent      = [double]$usage
            }
        }
        'Linux' {
            $cpuInfo = @{}
            $coreCount = 0
            if (Test-Path '/proc/cpuinfo') {
                $lines = Get-Content '/proc/cpuinfo'
                foreach ($line in $lines) {
                    if ($line -match '^model name\s*:\s*(.+)') {
                        $cpuInfo['Name'] = $Matches[1].Trim()
                    }
                    if ($line -match '^cpu cores\s*:\s*(\d+)') {
                        $cpuInfo['PhysicalCores'] = [int]$Matches[1]
                    }
                    if ($line -match '^processor\s*:') {
                        $coreCount++
                    }
                    if ($line -match '^cpu MHz\s*:\s*([\d.]+)') {
                        $cpuInfo['MaxClockSpeedMHz'] = [int][math]::Round([double]$Matches[1])
                    }
                }
            }
            # CPU usage from /proc/stat snapshot
            $usage = 0.0
            try {
                $stat1 = (Get-Content '/proc/stat' | Select-Object -First 1).Trim() -split '\s+'
                Start-Sleep -Milliseconds 200
                $stat2 = (Get-Content '/proc/stat' | Select-Object -First 1).Trim() -split '\s+'
                $idle1 = [long]$stat1[4]; $idle2 = [long]$stat2[4]
                $total1 = ($stat1[1..10] | ForEach-Object { [long]$_ } | Measure-Object -Sum).Sum
                $total2 = ($stat2[1..10] | ForEach-Object { [long]$_ } | Measure-Object -Sum).Sum
                $totalDelta = $total2 - $total1
                $idleDelta = $idle2 - $idle1
                if ($totalDelta -gt 0) {
                    $usage = [math]::Round((1 - $idleDelta / $totalDelta) * 100, 2)
                }
            }
            catch { $usage = 0.0 }

            [PSCustomObject]@{
                Name              = $cpuInfo['Name'] ?? 'Unknown'
                PhysicalCores     = $cpuInfo['PhysicalCores'] ?? 0
                LogicalProcessors = $coreCount
                MaxClockSpeedMHz  = $cpuInfo['MaxClockSpeedMHz'] ?? 0
                UsagePercent      = $usage
            }
        }
        'macOS' {
            $name = (sysctl -n machdep.cpu.brand_string 2>/dev/null) ?? 'Unknown'
            $phys = [int]((sysctl -n hw.physicalcpu 2>/dev/null) ?? 0)
            $logical = [int]((sysctl -n hw.logicalcpu 2>/dev/null) ?? 0)
            $freqHz = [long]((sysctl -n hw.cpufrequency 2>/dev/null) ?? 0)
            $freqMHz = [int]($freqHz / 1000000)
            # macOS has no trivial single-call CPU usage; approximate via ps
            $usage = 0.0
            try {
                $usage = [math]::Round(
                    ((Invoke-PlatformCommand 'ps' @('-A', '-o', '%cpu')) |
                        ForEach-Object { if ($_ -match '^\s*([\d.]+)') { [double]$Matches[1] } } |
                        Measure-Object -Sum).Sum / $logical, 2)
            }
            catch {}

            [PSCustomObject]@{
                Name              = $name.Trim()
                PhysicalCores     = $phys
                LogicalProcessors = $logical
                MaxClockSpeedMHz  = $freqMHz
                UsagePercent      = $usage
            }
        }
        default {
            [PSCustomObject]@{
                Name              = 'Unknown'
                PhysicalCores     = 0
                LogicalProcessors = 0
                MaxClockSpeedMHz  = 0
                UsagePercent      = 0.0
            }
        }
    }
}