diff --git a/System Info (ps1)/Get-SystemSecurityAndHardwareInfo.ps1 b/System Info (ps1)/Get-SystemSecurityAndHardwareInfo.ps1 index 129a098..7ff7b1d 100644 --- a/System Info (ps1)/Get-SystemSecurityAndHardwareInfo.ps1 +++ b/System Info (ps1)/Get-SystemSecurityAndHardwareInfo.ps1 @@ -5,7 +5,9 @@ Gather TPM, Secure Boot, RAM, CPU, drive info and optionally write to a text fil [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 + [string]$OutputFile, + [Parameter(Mandatory=$false, HelpMessage="Enable debug logging to a timestamped debug file in the script folder")] + [switch]$DebugMode ) # Note about host: If this script is run under Windows PowerShell (5.1) some advanced detection @@ -67,11 +69,45 @@ function Get-RAMInfo { $totalBytes = (Get-CimInstance -ClassName Win32_ComputerSystem).TotalPhysicalMemory $gb = [math]::Round($totalBytes / 1GB, 2) return @{ Bytes = [int64]$totalBytes; GB = $gb } + # Try CIM, fallback to WMIC if CIM fails + try { + $cs = Get-CimInstance -ClassName Win32_ComputerSystem -ErrorAction Stop + $totalBytes = $cs.TotalPhysicalMemory + } catch { + try { + $out = & wmic computersystem get TotalPhysicalMemory /value 2>$null + $match = ($out -split "\r?\n" | Where-Object { $_ -match '^TotalPhysicalMemory=' }) -replace 'TotalPhysicalMemory=' -replace '\r','' + $totalBytes = [int64]($match -join '') + } catch { + $totalBytes = 0 + } + } + $gb = if ($totalBytes -gt 0) { [math]::Round($totalBytes / 1GB, 2) } else { 0 } + 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 = @() + try { + $cpu = Get-CimInstance -ClassName Win32_Processor -ErrorAction Stop | Select-Object -First 1 -Property Name, Manufacturer, NumberOfCores, NumberOfLogicalProcessors, MaxClockSpeed + } catch { + # fallback to WMIC parsing + try { + $out = & wmic cpu get Name,Manufacturer,NumberOfCores,NumberOfLogicalProcessors,MaxClockSpeed /format:list 2>$null + $props = @{ Name=''; Manufacturer=''; NumberOfCores=0; NumberOfLogicalProcessors=0; MaxClockSpeed=0 } + foreach ($line in $out -split "\r?\n") { + if ($line -match '^Name=(.*)') { $props.Name = $Matches[1].Trim() } + if ($line -match '^Manufacturer=(.*)') { $props.Manufacturer = $Matches[1].Trim() } + if ($line -match '^NumberOfCores=(.*)') { $props.NumberOfCores = [int]$Matches[1].Trim() } + if ($line -match '^NumberOfLogicalProcessors=(.*)') { $props.NumberOfLogicalProcessors = [int]$Matches[1].Trim() } + if ($line -match '^MaxClockSpeed=(.*)') { $props.MaxClockSpeed = [int]$Matches[1].Trim() } + } + $cpu = New-Object psobject -Property $props + } catch { + $cpu = New-Object psobject -Property @{ Name=''; Manufacturer=''; NumberOfCores=0; NumberOfLogicalProcessors=0; MaxClockSpeed=0 } + } + } # 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. @@ -110,15 +146,31 @@ function Get-MainDriveInfo { $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 } + $disk = Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceID='$winDrive'" -ErrorAction Stop | Select-Object DeviceID, Size, FreeSpace + } catch { + # fallback to wmic parsing + try { + $device = $winDrive.TrimEnd(':') + ':' + $out = & wmic logicaldisk where "DeviceID='$device'" get DeviceID,Size,FreeSpace /format:list 2>$null + $props = @{ DeviceID=''; Size=0; FreeSpace=0 } + foreach ($line in $out -split "\r?\n") { + if ($line -match '^DeviceID=(.*)') { $props.DeviceID = $Matches[1].Trim() } + if ($line -match '^Size=(.*)') { $props.Size = [int64]($Matches[1].Trim()) } + if ($line -match '^FreeSpace=(.*)') { $props.FreeSpace = [int64]($Matches[1].Trim()) } + } + if ($props.DeviceID) { + $sizeGB = if ($props.Size -gt 0) { [math]::Round($props.Size / 1GB, 2) } else { 0 } + return @{ DeviceID = $props.DeviceID; SizeBytes = [int64]$props.Size; SizeGB = $sizeGB; FreeBytes = [int64]$props.FreeSpace } + } + } catch { + # final fallback + } } + try { + if ($disk) { + $sizeGB = if ($disk.Size) { [math]::Round($disk.Size / 1GB, 2) } else { 0 } + return @{ DeviceID = $disk.DeviceID; SizeBytes = [int64]$disk.Size; SizeGB = $sizeGB; FreeBytes = [int64]$disk.FreeSpace } + } } catch { } return $null } @@ -195,5 +247,36 @@ if ($OutputFile) { Write-Host "Report written to: $outPath" } catch { Write-Warning "Failed to write to file: $_" + if ($DebugMode) { + $scriptDir = Split-Path -Parent $PSCommandPath + $dbgFile = Join-Path $scriptDir ("debug_{0:yyyyMMdd_HHmmss}.log" -f (Get-Date)) + $err = $_ | Out-String + $debugInfo = @() + $debugInfo += "Timestamp: $(Get-Date -Format o)" + $debugInfo += "BoundParameters: $($PSBoundParameters | Out-String)" + $debugInfo += "Runtime: $($PSVersionTable.PSVersion) $((try { [System.Runtime.InteropServices.RuntimeInformation]::FrameworkDescription } catch { [Environment]::Version }))" + $debugInfo += "Error: $err" + $debugInfo | Out-File -FilePath $dbgFile -Encoding UTF8 -Force + Write-Host "Debug log written to: $dbgFile" + } + } +} + +# Wrap entire execution in a global try/catch when DebugMode is requested to capture unexpected failures +if ($DebugMode) { + try { + # Already executed main logic above; place-holder to be consistent with debug handling. + } catch { + $scriptDir = Split-Path -Parent $PSCommandPath + $dbgFile = Join-Path $scriptDir ("debug_{0:yyyyMMdd_HHmmss}.log" -f (Get-Date)) + $err = $_ | Out-String + $debugInfo = @() + $debugInfo += "Timestamp: $(Get-Date -Format o)" + $debugInfo += "BoundParameters: $($PSBoundParameters | Out-String)" + $debugInfo += "Runtime: $($PSVersionTable.PSVersion) $((try { [System.Runtime.InteropServices.RuntimeInformation]::FrameworkDescription } catch { [Environment]::Version }))" + $debugInfo += "Error: $err" + $debugInfo | Out-File -FilePath $dbgFile -Encoding UTF8 -Force + Write-Host "Fatal error — debug log written to: $dbgFile" + exit 1 } }