<# Get-SystemSecurityAndHardwareInfo.ps1 Gather TPM, Secure Boot, RAM, CPU, drive info and optionally write to a text file. #> [CmdletBinding()] param( [Parameter(Mandatory=$false, HelpMessage="Path or filename to write output to as a .txt file. If a relative filename is provided it will be created in the script folder.")] [string]$OutputFile ) # Note about host: If this script is run under Windows PowerShell (5.1) some advanced detection # (CPU intrinsics via System.Runtime.Intrinsics) will be unavailable. If you want a single # copy-paste one-liner that automatically runs the script under pwsh (PowerShell 7+) use the # following pattern (recommended when piping from the web): # # iwr -UseBasicParsing "https://git.smartcraft.me/Smartcraft-Media-Tech/System-Info/raw/branch/master/System%20Info%20%28ps1%29/Get-SystemSecurityAndHardwareInfo.ps1" | & pwsh -Command - # # This will fetch the script and execute it under pwsh so instruction-set detection works. function Get-TPMStatus { # Try CIM first (Windows 10/11) try { $tpm = Get-CimInstance -Namespace "root\cimv2\security\microsofttpm" -ClassName Win32_Tpm -ErrorAction Stop if ($tpm -and $tpm.IsEnabled_InitialValue -ne $null) { return @{ Installed = $true; IsEnabled = ($tpm.IsActivated_InitialValue -eq $true) -or ($tpm.IsEnabled_InitialValue -eq $true); ManufacturerId = $tpm.ManufacturerID; SpecVersion = $tpm.SpecVersion } } } catch { # fallback to registry check } # Registry fallback (may require elevated privileges) try { $reg = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Services\TPM' -ErrorAction Stop return @{ Installed = $true; IsEnabled = $true; ManufacturerId = $null; SpecVersion = $null } } catch { return @{ Installed = $false; IsEnabled = $false; ManufacturerId = $null; SpecVersion = $null } } } function Get-SecureBootStatus { # Use Confirm-SecureBootUEFI where available (PowerShell 5+) try { if (Get-Command -Name Confirm-SecureBootUEFI -ErrorAction SilentlyContinue) { $sb = Confirm-SecureBootUEFI return $sb } } catch { # continue to WMI } try { $sbState = (Get-CimInstance -Namespace root\wmi -ClassName MSSmBios_RawSMBiosTables -ErrorAction Stop) } catch { # can't determine } # If Confirm-SecureBootUEFI unavailable, try checking UEFI SecureBoot in registry (works on modern Windows) try { $val = Get-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State' -Name UEFISecureBootEnabled -ErrorAction Stop return ($val.UEFISecureBootEnabled -eq 1) } catch { return $null } } function Get-RAMInfo { $totalBytes = (Get-CimInstance -ClassName Win32_ComputerSystem).TotalPhysicalMemory $gb = [math]::Round($totalBytes / 1GB, 2) return @{ Bytes = [int64]$totalBytes; GB = $gb } } function Get-CPUInfo { $cpu = Get-CimInstance -ClassName Win32_Processor | Select-Object -First 1 -Property Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, MaxClockSpeed $instr = @() # Detect instruction sets using built-in .NET intrinsics when available (PowerShell 7+ / .NET Core+). # This avoids any third-party/native helpers and uses only system-provided types. try { # x86/x64 intrinsics if ([Type]::GetType("System.Runtime.Intrinsics.X86.Sse") -ne $null) { if ([System.Runtime.Intrinsics.X86.Sse]::IsSupported) { $instr += 'SSE' } if ([System.Runtime.Intrinsics.X86.Sse2]::IsSupported) { $instr += 'SSE2' } if ([System.Runtime.Intrinsics.X86.Sse3]::IsSupported) { $instr += 'SSE3' } if ([System.Runtime.Intrinsics.X86.Sse41]::IsSupported) { $instr += 'SSE4.1' } if ([System.Runtime.Intrinsics.X86.Sse42]::IsSupported) { $instr += 'SSE4.2' } if ([System.Runtime.Intrinsics.X86.Popcnt]::IsSupported) { $instr += 'POPCNT' } if ([System.Runtime.Intrinsics.X86.Avx]::IsSupported) { $instr += 'AVX' } if ([System.Runtime.Intrinsics.X86.Avx2]::IsSupported) { $instr += 'AVX2' } if ([Type]::GetType("System.Runtime.Intrinsics.X86.Bmi1") -ne $null -and [System.Runtime.Intrinsics.X86.Bmi1]::IsSupported) { $instr += 'BMI1' } if ([Type]::GetType("System.Runtime.Intrinsics.X86.Bmi2") -ne $null -and [System.Runtime.Intrinsics.X86.Bmi2]::IsSupported) { $instr += 'BMI2' } } # ARM intrinsics (if running on ARM/ARM64) if ([Type]::GetType("System.Runtime.Intrinsics.Arm.ArmBase") -ne $null) { if ([System.Runtime.Intrinsics.Arm.ArmBase]::IsSupported) { $instr += 'ARM_BASE' } if ([Type]::GetType("System.Runtime.Intrinsics.Arm.AdvSimd") -ne $null -and [System.Runtime.Intrinsics.Arm.AdvSimd]::IsSupported) { $instr += 'AdvSimd' } if ([Type]::GetType("System.Runtime.Intrinsics.Arm.Crc32") -ne $null -and [System.Runtime.Intrinsics.Arm.Crc32]::IsSupported) { $instr += 'CRC32' } if ([Type]::GetType("System.Runtime.Intrinsics.Arm.Sha1") -ne $null -and [System.Runtime.Intrinsics.Arm.Sha1]::IsSupported) { $instr += 'SHA1' } if ([Type]::GetType("System.Runtime.Intrinsics.Arm.Sha256") -ne $null -and [System.Runtime.Intrinsics.Arm.Sha256]::IsSupported) { $instr += 'SHA256' } } } catch { # If intrinsics types are not present (e.g., Windows PowerShell / .NET Framework), fall back to leaving the list empty. } return @{ Name = $cpu.Name; Manufacturer = $cpu.Manufacturer; Cores = $cpu.NumberOfCores; LogicalProcessors = $cpu.NumberOfLogicalProcessors; MaxClockMHz = $cpu.MaxClockSpeed; InstructionSets = $instr } } function Get-MainDriveInfo { # Determine system drive (where Windows is installed). $env:SystemDrive is like 'C:' so keep it as-is. $winDrive = $env:SystemDrive try { # Use the drive string directly (e.g. 'C:') in the WMI filter. Avoid trailing colon after the variable to prevent parser errors. $disk = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceID='$winDrive'" | Select-Object DeviceID, Size, FreeSpace if (-not $disk) { # fallback to C: if above fails $disk = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceID='C:'" | Select-Object DeviceID, Size, FreeSpace } if ($disk) { $sizeGB = [math]::Round($disk.Size / 1GB, 2) return @{ DeviceID = $disk.DeviceID; SizeBytes = [int64]$disk.Size; SizeGB = $sizeGB; FreeBytes = [int64]$disk.FreeSpace } } } catch { } return $null } # Build output $runtimeInfo = [ordered]@{} $runtimeInfo.PSVersion = $PSVersionTable.PSVersion.ToString() try { $runtimeInfo.Framework = [System.Runtime.InteropServices.RuntimeInformation]::FrameworkDescription } catch { $runtimeInfo.Framework = [string]([Environment]::Version) } $result = [ordered]@{} $result.Runtime = $runtimeInfo $result.TPM = Get-TPMStatus $result.SecureBoot = Get-SecureBootStatus $result.RAM = Get-RAMInfo $result.CPU = Get-CPUInfo $result.MainDrive = Get-MainDriveInfo function Format-ResultText($res) { $lines = @() $lines += "System Hardware & Security Report - $(Get-Date -Format 'u')" $lines += "" $lines += "TPM Installed: $($res.TPM.Installed)" $lines += "TPM Enabled/Activated: $($res.TPM.IsEnabled)" if ($res.TPM.ManufacturerId) { $lines += "TPM ManufacturerId: $($res.TPM.ManufacturerId)" } if ($res.TPM.SpecVersion) { $lines += "TPM SpecVersion: $($res.TPM.SpecVersion)" } $lines += "" $sb = $res.SecureBoot if ($sb -eq $null) { $lines += "Secure Boot: Unknown (insufficient privileges or unsupported)" } else { $lines += "Secure Boot Enabled: $sb" } $lines += "" $lines += "Installed RAM: $($res.RAM.GB) GB ($([string]::Format('{0:N0}', $res.RAM.Bytes)) bytes)" $lines += "" $lines += "CPU: $($res.CPU.Name)" $lines += "CPU Manufacturer: $($res.CPU.Manufacturer)" $lines += "CPU Cores: $($res.CPU.Cores) Logical Processors: $($res.CPU.LogicalProcessors) MaxClockMHz: $($res.CPU.MaxClockMHz)" if ($res.CPU.InstructionSets.Count -gt 0) { $lines += "CPU Instruction Sets: $($res.CPU.InstructionSets -join ', ')" } else { $lines += "CPU Instruction Sets: Not available on this runtime. Try running under PowerShell 7+ (pwsh) for full detection." } $lines += "" $lines += "Runtime: PowerShell $($res.Runtime.PSVersion) $($res.Runtime.Framework)" $lines += "" if ($res.MainDrive) { $lines += "Main Drive ($($res.MainDrive.DeviceID)) Size: $($res.MainDrive.SizeGB) GB ($([string]::Format('{0:N0}', $res.MainDrive.SizeBytes)) bytes) Free: $([math]::Round($res.MainDrive.FreeBytes/1GB,2)) GB" } else { $lines += "Main Drive: Unknown" } return $lines -join "`n" } $outText = Format-ResultText -res $result # Output to console Write-Host $outText # Output to file if requested via -OutputFile if ($OutputFile) { try { $scriptDir = Split-Path -Parent $PSCommandPath # If the provided path is rooted, use it; otherwise combine with script directory. if ([System.IO.Path]::IsPathRooted($OutputFile)) { $outPath = [System.IO.Path]::GetFullPath($OutputFile) } else { $outPath = [System.IO.Path]::GetFullPath((Join-Path $scriptDir $OutputFile)) } # Ensure .txt extension is present if ([System.IO.Path]::GetExtension($outPath) -eq '') { $outPath = "$outPath.txt" } $outText | Out-File -FilePath $outPath -Encoding UTF8 -Force Write-Host "Report written to: $outPath" } catch { Write-Warning "Failed to write to file: $_" } }