Update m365/diag.ps1
This commit is contained in:
1 parent
2041eb1985
commit
9813bbba9f
1 file changed
+121
-121
+121
-121
@@ -1,7 +1,7 @@
|
||||
# diag.ps1 - Laptop/Surface diagnose voor Maandag
|
||||
# Gebruik: irm https://<short-url> | iex (OOBE via Shift+F10 > powershell, of bij gebruiker)
|
||||
# Werkt met en zonder admin. Zonder admin worden enkele onderdelen overgeslagen en gemeld.
|
||||
# Rapport: C:\Diag\<model>_<serial>_<datum>.txt + regel in C:\Diag\summary.csv
|
||||
# diag.ps1 - Laptop/Surface diagnostics
|
||||
# Usage: irm https://<short-url> | iex (OOBE via Shift+F10 > powershell, or on a user's session)
|
||||
# Works with and without admin. Without admin some checks are skipped and reported as such.
|
||||
# Report: C:\Diag\<model>_<serial>_<date>.txt + one line in C:\Diag\summary.csv
|
||||
|
||||
$ErrorActionPreference = 'SilentlyContinue'
|
||||
$ProgressPreference = 'SilentlyContinue'
|
||||
@@ -14,12 +14,12 @@ function Test-Admin {
|
||||
function GB($b) { if ($b) { [math]::Round($b / 1GB, 1) } else { 0 } }
|
||||
$isAdmin = Test-Admin
|
||||
$lines = New-Object System.Collections.Generic.List[string]
|
||||
$flags = New-Object System.Collections.Generic.List[object] # ROOD / ORANJE / INFO
|
||||
$flags = New-Object System.Collections.Generic.List[object] # RED / ORANGE / INFO
|
||||
function Add($t = '') { $lines.Add($t) }
|
||||
function Flag($sev, $txt) { $flags.Add([pscustomobject]@{ Sev = $sev; Txt = $txt }) }
|
||||
$today = Get-Date
|
||||
|
||||
# ============ systeem ============
|
||||
# ============ system ============
|
||||
$cs = Get-CimInstance Win32_ComputerSystem
|
||||
$csp = Get-CimInstance Win32_ComputerSystemProduct
|
||||
$bios = Get-CimInstance Win32_BIOS
|
||||
@@ -31,7 +31,7 @@ $model = $cs.Model
|
||||
$sku = $csp.Version
|
||||
$serial = $bios.SerialNumber
|
||||
$ramGB = GB $cs.TotalPhysicalMemory
|
||||
$fw = $env:firmware_type; if (-not $fw) { $fw = 'onbekend' }
|
||||
$fw = $env:firmware_type; if (-not $fw) { $fw = 'unknown' }
|
||||
$fwVer = $bios.SMBIOSBIOSVersion
|
||||
$fwDate = $bios.ReleaseDate
|
||||
$osName = $os.Caption
|
||||
@@ -42,7 +42,7 @@ $uptime = if ($lastBoot) { [math]::Round(($today - $lastBoot).TotalDays, 1) }
|
||||
$sbReg = Get-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\SecureBoot\State'
|
||||
$secureBoot = if ($sbReg) { [bool]$sbReg.UEFISecureBootEnabled } else { $null }
|
||||
|
||||
# Surface model > releasejaar (Microsoft geeft doorgaans 6 jaar firmware/driver-support na release)
|
||||
# Surface model > release year (Microsoft typically provides 6 years of firmware/driver support after release)
|
||||
$surfaceYears = @(
|
||||
@('Surface Pro, 11th', 2024), @('Surface Pro 10', 2024), @('Surface Pro 9', 2022), @('Surface Pro 8', 2021),
|
||||
@('Surface Pro 7+', 2021), @('Surface Pro 7', 2019), @('Surface Pro 6', 2018), @('Surface Pro X', 2019),
|
||||
@@ -59,16 +59,16 @@ $releaseYear = $null
|
||||
foreach ($e in $surfaceYears) { if ($model -match "^$($e[0])") { $releaseYear = $e[1]; break } }
|
||||
$ageYears = if ($releaseYear) { $today.Year - $releaseYear } else { $null }
|
||||
if ($ageYears -ne $null) {
|
||||
if ($ageYears -ge 7) { Flag 'ROOD' "Model uit $releaseYear ($ageYears jaar): buiten het Surface-supportwindow, geen firmware/driver-updates meer te verwachten" }
|
||||
elseif ($ageYears -ge 6) { Flag 'ORANJE' "Model uit $releaseYear ($ageYears jaar): aan het einde van het Surface-supportwindow" }
|
||||
elseif ($ageYears -ge 4) { Flag 'INFO' "Model uit $releaseYear ($ageYears jaar)" }
|
||||
} elseif ($model -like 'Surface*') { Flag 'INFO' "Surface-model niet in de jaartabel: $model" }
|
||||
if ($ageYears -ge 7) { Flag 'RED' "Model from $releaseYear ($ageYears years): outside the Surface support window, no more firmware/driver updates expected" }
|
||||
elseif ($ageYears -ge 6) { Flag 'ORANGE' "Model from $releaseYear ($ageYears years): at the end of the Surface support window" }
|
||||
elseif ($ageYears -ge 4) { Flag 'INFO' "Model from $releaseYear ($ageYears years)" }
|
||||
} elseif ($model -like 'Surface*') { Flag 'INFO' "Surface model not in year table: $model" }
|
||||
|
||||
if ($fwDate -and ($today - $fwDate).TotalDays -gt 548) {
|
||||
Flag 'ORANJE' "Firmware van $($fwDate.ToString('yyyy-MM-dd')): ruim 1,5 jaar oud, device krijgt geen updates (meer) of is lang niet bijgewerkt"
|
||||
Flag 'ORANGE' "Firmware dated $($fwDate.ToString('yyyy-MM-dd')): over 1.5 years old, device no longer receives updates or has not been updated in a long time"
|
||||
}
|
||||
|
||||
# ============ Windows-versie en support ============
|
||||
# ============ Windows version and support ============
|
||||
$isEnt = ($osName -match 'Enterprise|Education')
|
||||
$eolTable = @{
|
||||
'W10-22H2' = @('2025-10-14', '2025-10-14')
|
||||
@@ -80,18 +80,18 @@ $eolTable = @{
|
||||
$osKey = if ($osName -like '*Windows 11*') { "W11-$osVer" } else { "W10-$osVer" }
|
||||
$eol = $null
|
||||
if ($eolTable[$osKey]) { $eol = [datetime]($eolTable[$osKey][ [int]$isEnt ]) }
|
||||
if ($osName -like '*Windows 10*') { Flag 'ROOD' "Draait nog Windows 10 ($osVer), einde support" }
|
||||
elseif ($eol -and $eol -lt $today) { Flag 'ORANJE' "Windows 11 $osVer is uit support sinds $($eol.ToString('yyyy-MM-dd')), feature-update nodig" }
|
||||
elseif ($eol -and ($eol - $today).TotalDays -lt 90) { Flag 'INFO' "Windows 11 $osVer loopt uit support op $($eol.ToString('yyyy-MM-dd'))" }
|
||||
if ($osName -like '*Windows 10*') { Flag 'RED' "Still running Windows 10 ($osVer), end of support" }
|
||||
elseif ($eol -and $eol -lt $today) { Flag 'ORANGE' "Windows 11 $osVer is out of support since $($eol.ToString('yyyy-MM-dd')), feature update required" }
|
||||
elseif ($eol -and ($eol - $today).TotalDays -lt 90) { Flag 'INFO' "Windows 11 $osVer goes out of support on $($eol.ToString('yyyy-MM-dd'))" }
|
||||
|
||||
$lastHotfix = (Get-HotFix | Where-Object InstalledOn | Sort-Object InstalledOn -Descending | Select-Object -First 1).InstalledOn
|
||||
if ($lastHotfix -and ($today - $lastHotfix).TotalDays -gt 90) { Flag 'ORANJE' "Laatste Windows-update op $($lastHotfix.ToString('yyyy-MM-dd')), meer dan 90 dagen geleden" }
|
||||
if ($lastHotfix -and ($today - $lastHotfix).TotalDays -gt 90) { Flag 'ORANGE' "Last Windows update on $($lastHotfix.ToString('yyyy-MM-dd')), more than 90 days ago" }
|
||||
|
||||
$lic = Get-CimInstance SoftwareLicensingProduct -Filter "PartialProductKey IS NOT NULL AND Name LIKE 'Windows%'" | Select-Object -First 1
|
||||
$activated = if ($lic) { $lic.LicenseStatus -eq 1 } else { $null }
|
||||
if ($activated -eq $false) { Flag 'INFO' 'Windows is niet geactiveerd' }
|
||||
if ($activated -eq $false) { Flag 'INFO' 'Windows is not activated' }
|
||||
|
||||
# ============ accu ============
|
||||
# ============ battery ============
|
||||
$batDesign = $null; $batFull = $null; $batCycles = $null; $batPct = $null
|
||||
$tmpXml = Join-Path $env:TEMP 'batteryreport.xml'
|
||||
Remove-Item $tmpXml -Force
|
||||
@@ -106,16 +106,16 @@ if (Test-Path $tmpXml) {
|
||||
Remove-Item $tmpXml -Force
|
||||
}
|
||||
$wb = Get-CimInstance Win32_Battery | Select-Object -First 1
|
||||
$batStatus = switch ($wb.BatteryStatus) { 1 {'ontladen'} 2 {'op netstroom'} 3 {'vol'} 4 {'laag'} 5 {'kritiek'} 6 {'laden'} 7 {'laden, hoog'} 8 {'laden, laag'} 9 {'laden, kritiek'} default {'onbekend'} }
|
||||
$batStatus = switch ($wb.BatteryStatus) { 1 {'discharging'} 2 {'on AC'} 3 {'full'} 4 {'low'} 5 {'critical'} 6 {'charging'} 7 {'charging, high'} 8 {'charging, low'} 9 {'charging, critical'} default {'unknown'} }
|
||||
$batCharge = $wb.EstimatedChargeRemaining
|
||||
if ($batPct -ne $null) {
|
||||
if ($batPct -lt 50) { Flag 'ROOD' "Accu op $batPct% van ontwerpcapaciteit, vervangen of afvoeren" }
|
||||
elseif ($batPct -lt 70) { Flag 'ORANJE' "Accu op $batPct% van ontwerpcapaciteit" }
|
||||
if ($batCycles -gt 800) { Flag 'ORANJE' "Accu heeft $batCycles laadcycli" }
|
||||
} elseif ($model -match 'Pro|Laptop|Go|Book') { Flag 'ORANJE' 'Geen accu-informatie beschikbaar op een mobiel device' }
|
||||
if ($batPct -lt 50) { Flag 'RED' "Battery at $batPct% of design capacity, replace or retire" }
|
||||
elseif ($batPct -lt 70) { Flag 'ORANGE' "Battery at $batPct% of design capacity" }
|
||||
if ($batCycles -gt 800) { Flag 'ORANGE' "Battery has $batCycles charge cycles" }
|
||||
} elseif ($model -match 'Pro|Laptop|Go|Book') { Flag 'ORANGE' 'No battery information available on a mobile device' }
|
||||
|
||||
# ============ schijf ============
|
||||
$diskModel = ''; $diskGB = 0; $diskHealth = 'onbekend'; $diskMedia = ''; $diskBus = ''
|
||||
# ============ disk ============
|
||||
$diskModel = ''; $diskGB = 0; $diskHealth = 'unknown'; $diskMedia = ''; $diskBus = ''
|
||||
$diskWear = $null; $diskTemp = $null; $diskPowerOn = $null; $diskRErr = $null; $diskWErr = $null
|
||||
$pd = Get-PhysicalDisk | Where-Object { $_.BusType -ne 'USB' } | Sort-Object Size -Descending | Select-Object -First 1
|
||||
if ($pd) {
|
||||
@@ -130,35 +130,35 @@ if ($pd) {
|
||||
}
|
||||
$sysDrive = Get-CimInstance Win32_LogicalDisk -Filter "DeviceID='$($env:SystemDrive)'"
|
||||
$freeGB = GB $sysDrive.FreeSpace
|
||||
if ($diskHealth -notin @('Healthy','OK','onbekend')) { Flag 'ROOD' "Schijf meldt status '$diskHealth'" }
|
||||
if ($diskHealth -notin @('Healthy','OK','unknown')) { Flag 'RED' "Disk reports status '$diskHealth'" }
|
||||
if ($diskWear -ne $null) {
|
||||
if ($diskWear -ge 80) { Flag 'ROOD' "SSD-slijtage $diskWear%, einde levensduur" }
|
||||
elseif ($diskWear -ge 50) { Flag 'ORANJE' "SSD-slijtage $diskWear%" }
|
||||
if ($diskWear -ge 80) { Flag 'RED' "SSD wear $diskWear%, end of life" }
|
||||
elseif ($diskWear -ge 50) { Flag 'ORANGE' "SSD wear $diskWear%" }
|
||||
}
|
||||
if (($diskRErr -gt 0) -or ($diskWErr -gt 0)) { Flag 'ROOD' "Schijf heeft niet-corrigeerbare fouten (lezen $diskRErr, schrijven $diskWErr)" }
|
||||
if ($diskMedia -eq 'HDD') { Flag 'ORANJE' 'Mechanische harde schijf, traag voor dagelijks gebruik' }
|
||||
if ($freeGB -lt 15) { Flag 'ORANJE' "Nog maar $freeGB GB vrij op $($env:SystemDrive)" }
|
||||
if (($diskRErr -gt 0) -or ($diskWErr -gt 0)) { Flag 'RED' "Disk has uncorrectable errors (read $diskRErr, write $diskWErr)" }
|
||||
if ($diskMedia -eq 'HDD') { Flag 'ORANGE' 'Mechanical hard drive, slow for daily use' }
|
||||
if ($freeGB -lt 15) { Flag 'ORANGE' "Only $freeGB GB free on $($env:SystemDrive)" }
|
||||
|
||||
# WinSAT-scores (als ooit gedraaid; schaal 1-9.9)
|
||||
# WinSAT scores (if ever run; scale 1-9.9)
|
||||
$ws = Get-CimInstance Win32_WinSAT
|
||||
if ($ws -and $ws.WinSATAssessmentState -eq 1) {
|
||||
if ($ws.DiskScore -lt 6.5) { Flag 'ORANJE' "WinSAT schijfscore $($ws.DiskScore) (laag)" }
|
||||
if ($ws.CPUScore -lt 6) { Flag 'ORANJE' "WinSAT CPU-score $($ws.CPUScore) (laag)" }
|
||||
if ($ws.DiskScore -lt 6.5) { Flag 'ORANGE' "WinSAT disk score $($ws.DiskScore) (low)" }
|
||||
if ($ws.CPUScore -lt 6) { Flag 'ORANGE' "WinSAT CPU score $($ws.CPUScore) (low)" }
|
||||
}
|
||||
|
||||
# BitLocker (admin)
|
||||
$blStatus = 'admin vereist'
|
||||
$blStatus = 'admin required'
|
||||
if ($isAdmin) {
|
||||
$bl = Get-BitLockerVolume -MountPoint $env:SystemDrive
|
||||
if ($bl) { $blStatus = "$($bl.ProtectionStatus) ($($bl.VolumeStatus), $($bl.EncryptionMethod))" } else { $blStatus = 'niet beschikbaar' }
|
||||
if ($bl -and $bl.ProtectionStatus -ne 'On') { Flag 'INFO' 'BitLocker staat niet aan op de systeemschijf' }
|
||||
if ($bl) { $blStatus = "$($bl.ProtectionStatus) ($($bl.VolumeStatus), $($bl.EncryptionMethod))" } else { $blStatus = 'not available' }
|
||||
if ($bl -and $bl.ProtectionStatus -ne 'On') { Flag 'INFO' 'BitLocker is not enabled on the system drive' }
|
||||
}
|
||||
|
||||
# ============ RAM ============
|
||||
$dimms = Get-CimInstance Win32_PhysicalMemory
|
||||
$ramSpeed = ($dimms | Select-Object -First 1).ConfiguredClockSpeed
|
||||
if ($ramGB -lt 7) { Flag 'ROOD' "$ramGB GB RAM, te weinig" }
|
||||
elseif ($ramGB -lt 15) { Flag 'ORANJE' "$ramGB GB RAM, krap voor Teams + Office + browser" }
|
||||
if ($ramGB -lt 7) { Flag 'RED' "$ramGB GB RAM, too little" }
|
||||
elseif ($ramGB -lt 15) { Flag 'ORANGE' "$ramGB GB RAM, tight for Teams + Office + browser" }
|
||||
|
||||
# ============ TPM / Secure Boot / Win11 ============
|
||||
$tpmPresent = $null; $tpmVersion = ''; $tpmReady = $null
|
||||
@@ -176,41 +176,41 @@ elseif ($cpuName -match 'Snapdragon|Microsoft SQ') { $cpuOk = $true }
|
||||
elseif ($cpuName -match 'Pentium|Celeron') { $cpuOk = $null }
|
||||
|
||||
$w11Checks = @(
|
||||
[pscustomobject]@{ Naam='TPM 2.0'; Ok = if ($tpmPresent -eq $null) { $null } else { ($tpmPresent -and $tpmVersion -like '2.*') } }
|
||||
[pscustomobject]@{ Naam='Secure Boot'; Ok = $secureBoot }
|
||||
[pscustomobject]@{ Naam='UEFI'; Ok = ($fw -eq 'UEFI') }
|
||||
[pscustomobject]@{ Naam='RAM >= 4GB'; Ok = ($ramGB -ge 4) }
|
||||
[pscustomobject]@{ Naam='Schijf >= 64GB'; Ok = ($diskGB -ge 64) }
|
||||
[pscustomobject]@{ Naam='CPU'; Ok = $cpuOk }
|
||||
[pscustomobject]@{ Name='TPM 2.0'; Ok = if ($tpmPresent -eq $null) { $null } else { ($tpmPresent -and $tpmVersion -like '2.*') } }
|
||||
[pscustomobject]@{ Name='Secure Boot'; Ok = $secureBoot }
|
||||
[pscustomobject]@{ Name='UEFI'; Ok = ($fw -eq 'UEFI') }
|
||||
[pscustomobject]@{ Name='RAM >= 4GB'; Ok = ($ramGB -ge 4) }
|
||||
[pscustomobject]@{ Name='Disk >= 64GB'; Ok = ($diskGB -ge 64) }
|
||||
[pscustomobject]@{ Name='CPU'; Ok = $cpuOk }
|
||||
)
|
||||
$w11Fail = @($w11Checks | Where-Object { $_.Ok -eq $false }).Count
|
||||
$w11Unknown = @($w11Checks | Where-Object { $_.Ok -eq $null }).Count
|
||||
if ($osName -like '*Windows 11*') { $w11Text = 'draait al Windows 11' }
|
||||
elseif ($w11Fail -gt 0) { $w11Text = 'NIET geschikt'; Flag 'ROOD' "Niet geschikt voor Windows 11: $(($w11Checks | Where-Object { $_.Ok -eq $false }).Naam -join ', ')" }
|
||||
elseif ($w11Unknown -gt 0) { $w11Text = 'onzeker (zie checks)' }
|
||||
else { $w11Text = 'geschikt' }
|
||||
if ($secureBoot -eq $false) { Flag 'ORANJE' 'Secure Boot staat uit' }
|
||||
if ($osName -like '*Windows 11*') { $w11Text = 'already running Windows 11' }
|
||||
elseif ($w11Fail -gt 0) { $w11Text = 'NOT eligible'; Flag 'RED' "Not eligible for Windows 11: $(($w11Checks | Where-Object { $_.Ok -eq $false }).Name -join ', ')" }
|
||||
elseif ($w11Unknown -gt 0) { $w11Text = 'uncertain (see checks)' }
|
||||
else { $w11Text = 'eligible' }
|
||||
if ($secureBoot -eq $false) { Flag 'ORANGE' 'Secure Boot is disabled' }
|
||||
|
||||
# ============ hardware / randapparatuur ============
|
||||
# ============ hardware / peripherals ============
|
||||
$pnpErr = Get-PnpDevice -PresentOnly | Where-Object { $_.Status -eq 'Error' -or $_.Status -eq 'Degraded' }
|
||||
$touch = Get-PnpDevice -PresentOnly | Where-Object { $_.FriendlyName -match 'touch screen|touchscreen' -and $_.Status -eq 'OK' }
|
||||
$camera = Get-PnpDevice -PresentOnly -Class Camera,Image | Where-Object Status -eq 'OK'
|
||||
$typeCover = Get-PnpDevice -PresentOnly | Where-Object { $_.FriendlyName -match 'Type Cover|Surface Keyboard|Surface Pro Keyboard' -and $_.Status -eq 'OK' }
|
||||
$wifi = Get-NetAdapter -Physical | Where-Object { $_.PhysicalMediaType -match '802.11|Native' -or $_.Name -match 'Wi-?Fi' } | Select-Object -First 1
|
||||
$wifiDrv = if ($wifi) { Get-NetAdapterAdvancedProperty -Name $wifi.Name | Out-Null; (Get-NetAdapter -Name $wifi.Name).DriverVersion } else { '' }
|
||||
$wifiDrv = if ($wifi) { (Get-NetAdapter -Name $wifi.Name).DriverVersion } else { '' }
|
||||
$bt = Get-PnpDevice -PresentOnly -Class Bluetooth | Where-Object Status -eq 'OK' | Select-Object -First 1
|
||||
$monitors = Get-CimInstance -Namespace root\wmi WmiMonitorID
|
||||
$res = if ($gpu) { "$($gpu.CurrentHorizontalResolution)x$($gpu.CurrentVerticalResolution)" } else { '' }
|
||||
|
||||
foreach ($d in $pnpErr) { Flag 'ORANJE' "Apparaat met probleem: $($d.FriendlyName) [$($d.Status), code $($d.ProblemCode)]" }
|
||||
if ($model -like 'Surface*' -and -not $touch) { Flag 'ORANJE' 'Geen werkend touchscreen gevonden (alle Surfaces hebben touch)' }
|
||||
if ($model -like 'Surface*' -and -not $camera) { Flag 'ORANJE' 'Geen werkende camera gevonden' }
|
||||
if (-not $wifi) { Flag 'ROOD' 'Geen wifi-adapter gevonden' }
|
||||
elseif ($wifi.Status -ne 'Up' -and $wifi.Status -ne 'Disconnected') { Flag 'ORANJE' "Wifi-adapter status: $($wifi.Status)" }
|
||||
if (-not $bt) { Flag 'INFO' 'Geen Bluetooth gevonden' }
|
||||
if ($model -match 'Surface Pro|Surface Go' -and -not $typeCover) { Flag 'INFO' 'Geen Type Cover aangesloten (niet getest)' }
|
||||
foreach ($d in $pnpErr) { Flag 'ORANGE' "Device with problem: $($d.FriendlyName) [$($d.Status), code $($d.ProblemCode)]" }
|
||||
if ($model -like 'Surface*' -and -not $touch) { Flag 'ORANGE' 'No working touchscreen found (all Surfaces have touch)' }
|
||||
if ($model -like 'Surface*' -and -not $camera) { Flag 'ORANGE' 'No working camera found' }
|
||||
if (-not $wifi) { Flag 'RED' 'No Wi-Fi adapter found' }
|
||||
elseif ($wifi.Status -ne 'Up' -and $wifi.Status -ne 'Disconnected') { Flag 'ORANGE' "Wi-Fi adapter status: $($wifi.Status)" }
|
||||
if (-not $bt) { Flag 'INFO' 'No Bluetooth found' }
|
||||
if ($model -match 'Surface Pro|Surface Go' -and -not $typeCover) { Flag 'INFO' 'No Type Cover attached (not tested)' }
|
||||
|
||||
# ============ stabiliteit (event log, 30 dagen) ============
|
||||
# ============ stability (event log, 30 days) ============
|
||||
$since = $today.AddDays(-30)
|
||||
$bsod = @(Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='Microsoft-Windows-WER-SystemErrorReporting'; Id=1001; StartTime=$since}).Count
|
||||
$kp41 = @(Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='Microsoft-Windows-Kernel-Power'; Id=41; StartTime=$since}).Count
|
||||
@@ -219,95 +219,95 @@ $diskEv = @(Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='disk
|
||||
$minidumps = @(Get-ChildItem "$env:SystemRoot\Minidump" -Filter *.dmp).Count
|
||||
$thermal = @(Get-WinEvent -FilterHashtable @{LogName='System'; ProviderName='Microsoft-Windows-Kernel-Processor-Power'; Id=37; StartTime=$since}).Count
|
||||
|
||||
if ($bsod -ge 3) { Flag 'ROOD' "$bsod blue screens in 30 dagen" }
|
||||
elseif ($bsod -ge 1){ Flag 'ORANJE' "$bsod blue screen(s) in 30 dagen" }
|
||||
if ($kp41 -ge 3) { Flag 'ORANJE' "$kp41 onverwachte uitval/herstarts (Kernel-Power 41) in 30 dagen: accu, oververhitting of crash" }
|
||||
if ($whea -gt 0) { Flag 'ROOD' "$whea hardwarefouten (WHEA) in 30 dagen: CPU/RAM/PCIe" }
|
||||
if ($diskEv -gt 0) { Flag 'ORANJE' "$diskEv schijf/NTFS-fouten in event log in 30 dagen" }
|
||||
if ($thermal -gt 5) { Flag 'ORANJE' "$thermal keer CPU teruggeschakeld (thermisch/power) in 30 dagen" }
|
||||
if ($minidumps -gt 0 -and $bsod -eq 0) { Flag 'INFO' "$minidumps crashdump(s) aanwezig (ouder dan 30 dagen)" }
|
||||
if ($bsod -ge 3) { Flag 'RED' "$bsod blue screens in 30 days" }
|
||||
elseif ($bsod -ge 1){ Flag 'ORANGE' "$bsod blue screen(s) in 30 days" }
|
||||
if ($kp41 -ge 3) { Flag 'ORANGE' "$kp41 unexpected shutdowns/reboots (Kernel-Power 41) in 30 days: battery, overheating or crash" }
|
||||
if ($whea -gt 0) { Flag 'RED' "$whea hardware errors (WHEA) in 30 days: CPU/RAM/PCIe" }
|
||||
if ($diskEv -gt 0) { Flag 'ORANGE' "$diskEv disk/NTFS errors in event log in 30 days" }
|
||||
if ($thermal -gt 5) { Flag 'ORANGE' "$thermal CPU throttling events (thermal/power) in 30 days" }
|
||||
if ($minidumps -gt 0 -and $bsod -eq 0) { Flag 'INFO' "$minidumps crash dump(s) present (older than 30 days)" }
|
||||
|
||||
# ============ beheer / identiteit ============
|
||||
# ============ management / identity ============
|
||||
$dsreg = dsregcmd /status 2>$null
|
||||
function DsVal($k) { ($dsreg | Where-Object { $_ -match "^\s*$k\s*:" } | Select-Object -First 1) -replace "^\s*$k\s*:\s*", '' }
|
||||
$aadJoined = DsVal 'AzureAdJoined'; $domainJoined = DsVal 'DomainJoined'; $tenant = DsVal 'TenantName'; $mdmUrl = DsVal 'MdmUrl'
|
||||
$mdm = if ($mdmUrl) { 'ja (Intune)' } else { 'nee' }
|
||||
$mdm = if ($mdmUrl) { 'yes (Intune)' } else { 'no' }
|
||||
$profiles = @(Get-CimInstance Win32_UserProfile | Where-Object { -not $_.Special })
|
||||
$profText = ($profiles | ForEach-Object { "$(Split-Path $_.LocalPath -Leaf) ($(GB $_.Size)GB, laatst $($_.LastUseTime.ToString('yyyy-MM-dd')))" }) -join '; '
|
||||
if ($aadJoined -eq 'YES' -and $mdm -eq 'nee') { Flag 'INFO' 'Entra joined maar niet in Intune' }
|
||||
if ($profiles.Count -gt 0) { Flag 'INFO' "$($profiles.Count) gebruikersprofiel(en) aanwezig, wipe nodig voor hergebruik" }
|
||||
$profText = ($profiles | ForEach-Object { "$(Split-Path $_.LocalPath -Leaf) ($(GB $_.Size)GB, last used $($_.LastUseTime.ToString('yyyy-MM-dd')))" }) -join '; '
|
||||
if ($aadJoined -eq 'YES' -and $mdm -eq 'no') { Flag 'INFO' 'Entra joined but not enrolled in Intune' }
|
||||
if ($profiles.Count -gt 0) { Flag 'INFO' "$($profiles.Count) user profile(s) present, wipe required before reuse" }
|
||||
|
||||
# ============ eindoordeel ============
|
||||
$red = @($flags | Where-Object Sev -eq 'ROOD'); $orange = @($flags | Where-Object Sev -eq 'ORANJE')
|
||||
if ($red.Count -gt 0) { $final = 'NIET GOED BRUIKBAAR (zie rode punten: repareren of afvoeren)' }
|
||||
elseif ($orange.Count -ge 3) { $final = 'TWIJFEL (meerdere oranje punten, beoordeel zelf)' }
|
||||
elseif ($orange.Count -gt 0) { $final = 'BRUIKBAAR MET KANTTEKENINGEN' }
|
||||
else { $final = 'GOED BRUIKBAAR' }
|
||||
if (-not $isAdmin) { $final += ' [zonder admin: SSD-slijtage, TPM en BitLocker niet gecontroleerd]' }
|
||||
# ============ verdict ============
|
||||
$red = @($flags | Where-Object Sev -eq 'RED'); $orange = @($flags | Where-Object Sev -eq 'ORANGE')
|
||||
if ($red.Count -gt 0) { $final = 'NOT FIT FOR USE (see red items: repair or retire)' }
|
||||
elseif ($orange.Count -ge 3) { $final = 'DOUBTFUL (multiple orange items, judge for yourself)' }
|
||||
elseif ($orange.Count -gt 0) { $final = 'USABLE WITH REMARKS' }
|
||||
else { $final = 'GOOD' }
|
||||
if (-not $isAdmin) { $final += ' [no admin: SSD wear, TPM and BitLocker not checked]' }
|
||||
|
||||
# ============ rapport ============
|
||||
# ============ report ============
|
||||
$now = $today.ToString('yyyy-MM-dd HH:mm')
|
||||
Add "=================================================================="
|
||||
Add " DIAGNOSE $model"
|
||||
Add " Serienummer $serial $now admin: $(if ($isAdmin) {'ja'} else {'nee'})"
|
||||
Add " DIAGNOSTICS $model"
|
||||
Add " Serial $serial $now admin: $(if ($isAdmin) {'yes'} else {'no'})"
|
||||
Add "=================================================================="
|
||||
Add ""
|
||||
Add " OORDEEL: $final"
|
||||
Add " VERDICT: $final"
|
||||
Add ""
|
||||
Add " SIGNALEN"
|
||||
if ($flags.Count -eq 0) { Add " geen" }
|
||||
foreach ($sev in 'ROOD','ORANJE','INFO') { foreach ($f in ($flags | Where-Object Sev -eq $sev)) { Add (" [{0,-6}] {1}" -f $sev, $f.Txt) } }
|
||||
Add " FINDINGS"
|
||||
if ($flags.Count -eq 0) { Add " none" }
|
||||
foreach ($sev in 'RED','ORANGE','INFO') { foreach ($f in ($flags | Where-Object Sev -eq $sev)) { Add (" [{0,-6}] {1}" -f $sev, $f.Txt) } }
|
||||
Add ""
|
||||
Add "------ Device ------"
|
||||
Add " Model: $model $(if ($sku) {"($sku)"}) release: $(if ($releaseYear) {"$releaseYear, $ageYears jaar"} else {'onbekend'})"
|
||||
Add " Serienummer: $serial naam: $env:COMPUTERNAME"
|
||||
Add " Model: $model $(if ($sku) {"($sku)"}) release: $(if ($releaseYear) {"$releaseYear, $ageYears years"} else {'unknown'})"
|
||||
Add " Serial: $serial name: $env:COMPUTERNAME"
|
||||
Add " CPU: $cpuName"
|
||||
Add " GPU: $($gpu.Name) scherm: $res monitoren: $(@($monitors).Count)"
|
||||
Add " GPU: $($gpu.Name) display: $res monitors: $(@($monitors).Count)"
|
||||
Add " RAM: $ramGB GB $(if ($ramSpeed) {"@ $ramSpeed MHz"}) ($(@($dimms).Count) module(s))"
|
||||
Add " Firmware: $fw versie $fwVer van $(if ($fwDate) {$fwDate.ToString('yyyy-MM-dd')})"
|
||||
Add " Secure Boot: $(if ($secureBoot -eq $null) {'onbekend'} elseif ($secureBoot) {'aan'} else {'UIT'})"
|
||||
Add " TPM: $(if ($tpmPresent -eq $null) {'admin vereist'} elseif ($tpmPresent) {"versie $tpmVersion, gereed: $tpmReady"} else {'NIET gevonden'})"
|
||||
Add " Firmware: $fw version $fwVer dated $(if ($fwDate) {$fwDate.ToString('yyyy-MM-dd')})"
|
||||
Add " Secure Boot: $(if ($secureBoot -eq $null) {'unknown'} elseif ($secureBoot) {'on'} else {'OFF'})"
|
||||
Add " TPM: $(if ($tpmPresent -eq $null) {'admin required'} elseif ($tpmPresent) {"version $tpmVersion, ready: $tpmReady"} else {'NOT found'})"
|
||||
Add ""
|
||||
Add "------ Windows ------"
|
||||
Add " Versie: $osName $osVer (build $osBuild) support tot: $(if ($eol) {$eol.ToString('yyyy-MM-dd')} else {'onbekend'})"
|
||||
Add " Activatie: $(if ($activated -eq $null) {'onbekend'} elseif ($activated) {'geactiveerd'} else {'NIET geactiveerd'})"
|
||||
Add " Laatste update: $(if ($lastHotfix) {$lastHotfix.ToString('yyyy-MM-dd')} else {'onbekend'}) uptime: $uptime dagen"
|
||||
Add " Version: $osName $osVer (build $osBuild) supported until: $(if ($eol) {$eol.ToString('yyyy-MM-dd')} else {'unknown'})"
|
||||
Add " Activation: $(if ($activated -eq $null) {'unknown'} elseif ($activated) {'activated'} else {'NOT activated'})"
|
||||
Add " Last update: $(if ($lastHotfix) {$lastHotfix.ToString('yyyy-MM-dd')} else {'unknown'}) uptime: $uptime days"
|
||||
Add " Windows 11: $w11Text"
|
||||
foreach ($c in $w11Checks) { $s = if ($c.Ok -eq $null) {'?'} elseif ($c.Ok) {'OK'} else {'NEE'}; Add (" {0,-16} {1}" -f $c.Naam, $s) }
|
||||
foreach ($c in $w11Checks) { $s = if ($c.Ok -eq $null) {'?'} elseif ($c.Ok) {'OK'} else {'NO'}; Add (" {0,-16} {1}" -f $c.Name, $s) }
|
||||
Add " BitLocker: $blStatus"
|
||||
Add ""
|
||||
Add "------ Accu ------"
|
||||
if ($batPct -eq $null) { Add " Geen accu-informatie" } else {
|
||||
Add " Capaciteit: $batFull / $batDesign mWh = $batPct %"
|
||||
Add " Laadcycli: $batCycles status nu: $batStatus, $batCharge %" }
|
||||
Add "------ Battery ------"
|
||||
if ($batPct -eq $null) { Add " No battery information" } else {
|
||||
Add " Capacity: $batFull / $batDesign mWh = $batPct %"
|
||||
Add " Cycles: $batCycles current: $batStatus, $batCharge %" }
|
||||
Add ""
|
||||
Add "------ Schijf ------"
|
||||
Add "------ Disk ------"
|
||||
Add " Model: $diskModel ($diskMedia, $diskBus)"
|
||||
Add " Grootte: $diskGB GB vrij op $($env:SystemDrive): $freeGB GB"
|
||||
Add " Size: $diskGB GB free on $($env:SystemDrive): $freeGB GB"
|
||||
Add " Health: $diskHealth"
|
||||
if ($diskWear -ne $null) { Add " Slijtage: $diskWear % temp $diskTemp C uren aan $diskPowerOn fouten R/W $diskRErr/$diskWErr" }
|
||||
elseif (-not $isAdmin) { Add " Slijtage: admin vereist" }
|
||||
if ($ws -and $ws.WinSATAssessmentState -eq 1) { Add " WinSAT: CPU $($ws.CPUScore) RAM $($ws.MemoryScore) schijf $($ws.DiskScore) GPU $($ws.GraphicsScore)" }
|
||||
if ($diskWear -ne $null) { Add " Wear: $diskWear % temp $diskTemp C power-on hours $diskPowerOn errors R/W $diskRErr/$diskWErr" }
|
||||
elseif (-not $isAdmin) { Add " Wear: admin required" }
|
||||
if ($ws -and $ws.WinSATAssessmentState -eq 1) { Add " WinSAT: CPU $($ws.CPUScore) RAM $($ws.MemoryScore) disk $($ws.DiskScore) GPU $($ws.GraphicsScore)" }
|
||||
Add ""
|
||||
Add "------ Hardware ------"
|
||||
Add " Touchscreen: $(if ($touch) {'OK'} else {'niet gevonden'}) camera: $(if ($camera) {'OK'} else {'niet gevonden'}) Bluetooth: $(if ($bt) {'OK'} else {'niet gevonden'})"
|
||||
Add " Wifi: $(if ($wifi) {"$($wifi.InterfaceDescription), $($wifi.Status), driver $wifiDrv"} else {'NIET gevonden'})"
|
||||
Add " Type Cover: $(if ($typeCover) {'aangesloten'} else {'niet aangesloten'})"
|
||||
Add " PnP-fouten: $(@($pnpErr).Count)"
|
||||
Add " Touchscreen: $(if ($touch) {'OK'} else {'not found'}) camera: $(if ($camera) {'OK'} else {'not found'}) Bluetooth: $(if ($bt) {'OK'} else {'not found'})"
|
||||
Add " Wi-Fi: $(if ($wifi) {"$($wifi.InterfaceDescription), $($wifi.Status), driver $wifiDrv"} else {'NOT found'})"
|
||||
Add " Type Cover: $(if ($typeCover) {'attached'} else {'not attached'})"
|
||||
Add " PnP errors: $(@($pnpErr).Count)"
|
||||
Add ""
|
||||
Add "------ Stabiliteit (30 dagen) ------"
|
||||
Add " Blue screens: $bsod onverwachte uitval: $kp41 WHEA: $whea schijffouten: $diskEv thermisch: $thermal dumps: $minidumps"
|
||||
Add "------ Stability (30 days) ------"
|
||||
Add " Blue screens: $bsod unexpected shutdowns: $kp41 WHEA: $whea disk errors: $diskEv thermal: $thermal dumps: $minidumps"
|
||||
Add ""
|
||||
Add "------ Beheer ------"
|
||||
Add "------ Management ------"
|
||||
Add " Entra joined: $aadJoined domain joined: $domainJoined tenant: $tenant"
|
||||
Add " Intune (MDM): $mdm"
|
||||
Add " Profielen: $(if ($profiles.Count) {$profText} else {'geen'})"
|
||||
Add " Profiles: $(if ($profiles.Count) {$profText} else {'none'})"
|
||||
Add ""
|
||||
Add "------ Niet getest (handmatig of via Surface Diagnostic Toolkit) ------"
|
||||
Add " Toetsenbord/trackpad, pixelfouten, scharnier/behuizing, luidspreker/microfoon, poorten, pen"
|
||||
Add "------ Not tested (manually or via Surface Diagnostic Toolkit) ------"
|
||||
Add " Keyboard/trackpad, dead pixels, hinge/chassis, speaker/microphone, ports, pen"
|
||||
Add ""
|
||||
|
||||
# ============ opslaan ============
|
||||
# ============ save ============
|
||||
$safeModel = ($model -replace '[^\w\-]', '_'); $safeSerial = ($serial -replace '[^\w\-]', '_')
|
||||
$fileName = "{0}_{1}_{2}.txt" -f $safeModel, $safeSerial, $today.ToString('yyyyMMdd-HHmm')
|
||||
$outDir = $null
|
||||
@@ -319,11 +319,11 @@ foreach ($try in @('C:\Diag', [Environment]::GetFolderPath('Desktop'), $env:TEMP
|
||||
$outFile = Join-Path $outDir $fileName
|
||||
$lines | Set-Content $outFile -Encoding UTF8
|
||||
|
||||
# samenvattingsregel voor vergelijken over meerdere devices
|
||||
# summary line for comparing multiple devices
|
||||
$csv = Join-Path $outDir 'summary.csv'
|
||||
if (-not (Test-Path $csv)) { 'Datum;Model;Serienummer;Oordeel;Rood;Oranje;AccuPct;Cycli;SSDwear;RAMGB;DiskGB;CPU;Windows;Win11;Release;Intune' | Set-Content $csv -Encoding UTF8 }
|
||||
if (-not (Test-Path $csv)) { 'Date;Model;Serial;Verdict;Red;Orange;BatteryPct;Cycles;SSDwear;RAMGB;DiskGB;CPU;Windows;Win11;Release;Intune' | Set-Content $csv -Encoding UTF8 }
|
||||
"$now;$model;$serial;$($final -replace '\s{2,}.*$','');$($red.Count);$($orange.Count);$batPct;$batCycles;$diskWear;$ramGB;$diskGB;$cpuName;$osName $osVer;$w11Text;$releaseYear;$mdm" | Add-Content $csv -Encoding UTF8
|
||||
|
||||
$lines | ForEach-Object { Write-Host $_ }
|
||||
Write-Host "Rapport: $outFile" -ForegroundColor Cyan
|
||||
Write-Host "Report: $outFile" -ForegroundColor Cyan
|
||||
if ($env:USERNAME -ne 'SYSTEM' -and $env:USERNAME -notlike '*$') { Start-Process notepad.exe $outFile }
|
||||
Reference in new issue
Block a user