diff --git a/m365/diag.ps1 b/m365/diag.ps1 new file mode 100644 index 0000000..1e7c8bb --- /dev/null +++ b/m365/diag.ps1 @@ -0,0 +1,225 @@ +# diag.ps1 - Laptop/Surface diagnose voor Maandag +# Werkt met en zonder admin. Zonder admin worden sommige onderdelen overgeslagen. +# Gebruik: powershell -ep bypass -f diag.ps1 (of start diag.cmd) +# Rapport: map Reports naast het script, anders %TEMP% + +$ErrorActionPreference = 'SilentlyContinue' +$ProgressPreference = 'SilentlyContinue' + +# ---------- helpers ---------- +function Test-Admin { + $id = [Security.Principal.WindowsIdentity]::GetCurrent() + (New-Object Security.Principal.WindowsPrincipal $id).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) +} +function GB($bytes) { if ($bytes) { [math]::Round($bytes / 1GB, 1) } else { 0 } } + +$isAdmin = Test-Admin +$lines = New-Object System.Collections.Generic.List[string] +$verdict = @{} # onderdeel -> goed / beperkt / slecht / onbekend +function Add($t = '') { $lines.Add($t) } + +# ---------- systeem ---------- +$cs = Get-CimInstance Win32_ComputerSystem +$bios = Get-CimInstance Win32_BIOS +$os = Get-CimInstance Win32_OperatingSystem +$cpu = Get-CimInstance Win32_Processor | Select-Object -First 1 + +$model = $cs.Model +$serial = $bios.SerialNumber +$ramGB = GB $cs.TotalPhysicalMemory +$fw = $env:firmware_type +if (-not $fw) { $fw = 'onbekend' } + +$sbReg = Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State' +$secureBoot = if ($sbReg) { [bool]$sbReg.UEFISecureBootEnabled } else { $null } + +$osName = $os.Caption +$osBuild = $os.BuildNumber +$osVer = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion').DisplayVersion + +# ---------- accu ---------- +$batDesign = $null; $batFull = $null; $batCycles = $null; $batPct = $null +$tmpXml = Join-Path $env:TEMP 'batteryreport.xml' +Remove-Item $tmpXml -Force +powercfg /batteryreport /xml /output $tmpXml | Out-Null +if (Test-Path $tmpXml) { + [xml]$bx = Get-Content $tmpXml + $b = $bx.BatteryReport.Batteries.Battery | Select-Object -First 1 + if ($b) { + $batDesign = [int]$b.DesignCapacity + $batFull = [int]$b.FullChargeCapacity + $batCycles = [int]$b.CycleCount + if ($batDesign -gt 0) { $batPct = [math]::Round(100 * $batFull / $batDesign) } + } + Remove-Item $tmpXml -Force +} +if ($batPct -eq $null) { + $verdict.Accu = 'nvt' +} elseif ($batPct -ge 70) { $verdict.Accu = 'goed' } +elseif ($batPct -ge 50) { $verdict.Accu = 'beperkt' } +else { $verdict.Accu = 'slecht' } + +# ---------- schijf ---------- +$diskModel = ''; $diskGB = 0; $diskHealth = 'onbekend'; $diskWear = $null; $diskTemp = $null; $diskPowerOn = $null; $diskStatus = '' +$pd = Get-PhysicalDisk | Where-Object { $_.BusType -ne 'USB' } | Sort-Object Size -Descending | Select-Object -First 1 +if ($pd) { + $diskModel = $pd.FriendlyName + $diskGB = GB $pd.Size + $diskHealth = "$($pd.HealthStatus)" + if ($isAdmin) { + $rc = $pd | Get-StorageReliabilityCounter + if ($rc) { + $diskWear = $rc.Wear + $diskTemp = $rc.Temperature + $diskPowerOn = $rc.PowerOnHours + } + } +} else { + $dd = Get-CimInstance Win32_DiskDrive | Where-Object { $_.InterfaceType -ne 'USB' } | Sort-Object Size -Descending | Select-Object -First 1 + if ($dd) { $diskModel = $dd.Model; $diskGB = GB $dd.Size; $diskStatus = $dd.Status } +} +$sysDrive = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='$($env:SystemDrive)'" +$freeGB = GB $sysDrive.FreeSpace + +if ($diskHealth -and $diskHealth -ne 'Healthy' -and $diskHealth -ne 'onbekend') { $verdict.Schijf = 'slecht' } +elseif ($diskStatus -and $diskStatus -ne 'OK') { $verdict.Schijf = 'slecht' } +elseif ($diskWear -ne $null) { + if ($diskWear -ge 80) { $verdict.Schijf = 'slecht' } + elseif ($diskWear -ge 50) { $verdict.Schijf = 'beperkt' } + else { $verdict.Schijf = 'goed' } +} +elseif ($diskHealth -eq 'Healthy') { $verdict.Schijf = 'goed (basis)' } +else { $verdict.Schijf = 'onbekend' } + +# ---------- RAM ---------- +if ($ramGB -ge 15) { $verdict.RAM = 'goed' } +elseif ($ramGB -ge 7) { $verdict.RAM = 'beperkt' } +else { $verdict.RAM = 'slecht' } + +# ---------- TPM ---------- +$tpmPresent = $null; $tpmVersion = '' +if ($isAdmin) { + $tpm = Get-CimInstance -Namespace root\cimv2\Security\MicrosoftTpm -ClassName Win32_Tpm + if ($tpm) { + $tpmPresent = $true + $tpmVersion = ($tpm.SpecVersion -split ',')[0].Trim() + } else { $tpmPresent = $false } +} + +# ---------- CPU / Windows 11 ---------- +$cpuName = $cpu.Name.Trim() +$cpuOk = $null +if ($cpuName -match 'Core\(TM\)\s+i[3579]-(\d{4,5})') { + $num = $matches[1] + $gen = if ($num.Length -eq 5) { [int]$num.Substring(0,2) } else { [int]$num.Substring(0,1) } + $cpuOk = $gen -ge 8 +} elseif ($cpuName -match 'Core\(TM\)\s+(Ultra|m3|m5|m7)') { + $cpuOk = ($matches[1] -eq 'Ultra') +} elseif ($cpuName -match 'Ryzen') { + $cpuOk = -not ($cpuName -match 'Ryzen\s+[357]\s+[12]\d{3}') # Ryzen 1000/2000 niet ondersteund +} elseif ($cpuName -match 'Snapdragon|Microsoft SQ') { + $cpuOk = $true +} + +$w11Checks = @() +$w11Checks += [pscustomobject]@{ Naam='TPM 2.0'; Ok = if ($tpmPresent -eq $null) { $null } else { ($tpmPresent -and $tpmVersion -like '2.*') } } +$w11Checks += [pscustomobject]@{ Naam='Secure Boot'; Ok = $secureBoot } +$w11Checks += [pscustomobject]@{ Naam='UEFI'; Ok = ($fw -eq 'UEFI') } +$w11Checks += [pscustomobject]@{ Naam='RAM >= 4GB'; Ok = ($ramGB -ge 4) } +$w11Checks += [pscustomobject]@{ Naam='Schijf >= 64GB'; Ok = ($diskGB -ge 64) } +$w11Checks += [pscustomobject]@{ Naam='CPU'; Ok = $cpuOk } + +$w11Fail = ($w11Checks | Where-Object { $_.Ok -eq $false }).Count +$w11Unknown = ($w11Checks | Where-Object { $_.Ok -eq $null }).Count +if ($osName -like '*Windows 11*') { $verdict.Win11 = 'draait al' } +elseif ($w11Fail -gt 0) { $verdict.Win11 = 'slecht' } +elseif ($w11Unknown -gt 0) { $verdict.Win11 = 'onbekend' } +else { $verdict.Win11 = 'goed' } + +# ---------- eindoordeel ---------- +$vals = $verdict.Values +if ($vals -contains 'slecht') { $final = 'AFVOEREN' } +elseif ($vals -contains 'beperkt') { $final = 'BEPERKT BRUIKBAAR' } +elseif ($vals -contains 'onbekend') { $final = 'BRUIKBAAR (admin nodig voor volledige check)' } +else { $final = 'BRUIKBAAR' } + +# ---------- rapport ---------- +$now = Get-Date -Format 'yyyy-MM-dd HH:mm' +Add "==================================================" +Add " LAPTOP DIAGNOSE - $model" +Add " Serienummer: $serial" +Add " Datum: $now Admin: $(if ($isAdmin) {'ja'} else {'nee'})" +Add "==================================================" +Add "" +Add " OORDEEL: $final" +Add "" +Add " Accu ........ $($verdict.Accu)" +Add " Schijf ...... $($verdict.Schijf)" +Add " RAM ......... $($verdict.RAM)" +Add " Windows 11 .. $($verdict.Win11)" +Add "" +Add "--- Systeem ---" +Add " Model: $model" +Add " Serienummer: $serial" +Add " CPU: $cpuName" +Add " RAM: $ramGB GB" +Add " Firmware: $fw Secure Boot: $(if ($secureBoot -eq $null) {'onbekend'} elseif ($secureBoot) {'aan'} else {'uit'})" +Add " TPM: $(if ($tpmPresent -eq $null) {'admin vereist'} elseif ($tpmPresent) {"aanwezig, versie $tpmVersion"} else {'niet gevonden'})" +Add " Windows: $osName $osVer (build $osBuild)" +Add " Device naam: $env:COMPUTERNAME" +Add "" +Add "--- Accu ---" +if ($batPct -eq $null) { + Add " Geen accu gevonden (of rapport niet beschikbaar)" +} else { + Add " Ontwerpcapaciteit: $batDesign mWh" + Add " Huidige capaciteit: $batFull mWh ($batPct %)" + Add " Laadcycli: $batCycles" +} +Add "" +Add "--- Schijf ---" +Add " Model: $diskModel" +Add " Grootte: $diskGB GB Vrij op $($env:SystemDrive): $freeGB GB" +Add " Health: $diskHealth $(if ($diskStatus) {"/ $diskStatus"})" +if ($diskWear -ne $null) { + Add " Slijtage: $diskWear % Temperatuur: $diskTemp C Uren aan: $diskPowerOn" +} elseif (-not $isAdmin) { + Add " Slijtage: admin vereist" +} +Add "" +Add "--- Windows 11 geschiktheid ---" +foreach ($c in $w11Checks) { + $s = if ($c.Ok -eq $null) { '?' } elseif ($c.Ok) { 'OK' } else { 'NEE' } + Add (" {0,-16} {1}" -f $c.Naam, $s) +} +if ($cpuOk -eq $null) { Add " (CPU niet automatisch herkend, handmatig controleren)" } +Add "" +Add "--- Toelichting oordeel ---" +Add " Accu: >=70% goed, 50-70% beperkt, <50% slecht" +Add " Schijf: slijtage <50% goed, 50-80% beperkt, >80% slecht; unhealthy = slecht" +Add " RAM: 16GB goed, 8GB beperkt, minder slecht" +Add " Win11: alle checks OK = goed, een NEE = slecht" +Add "" + +# ---------- opslaan ---------- +$safeModel = ($model -replace '[^\w\-]', '_') +$safeSerial = ($serial -replace '[^\w\-]', '_') +$fileName = "{0}_{1}_{2}.txt" -f $safeModel, $safeSerial, (Get-Date -Format 'yyyyMMdd-HHmm') + +# Script draait via "irm url | iex", dus geen scriptmap. Probeer C:\Diag, anders Desktop, anders TEMP. +$outDir = $null +foreach ($try in @('C:\Diag', [Environment]::GetFolderPath('Desktop'), $env:TEMP)) { + if (-not $try) { continue } + New-Item $try -ItemType Directory -Force | Out-Null + try { [IO.File]::WriteAllText((Join-Path $try '.w'), 'x'); Remove-Item (Join-Path $try '.w') -Force; $outDir = $try; break } catch {} +} +$outFile = Join-Path $outDir $fileName +$lines | Set-Content $outFile -Encoding UTF8 + +$lines | ForEach-Object { Write-Host $_ } +Write-Host "Rapport opgeslagen: $outFile" -ForegroundColor Cyan + +# Bij een gewone gebruiker (niet OOBE/SYSTEM): rapport openen zodat hij het kan doorsturen +if ($env:USERNAME -ne 'SYSTEM' -and $env:USERNAME -notlike '*$') { + Start-Process notepad.exe $outFile +} \ No newline at end of file