From 0e1b80b903fe592d44d5ef27d0e1cea16ba6288e Mon Sep 17 00:00:00 2001 From: cproudlock Date: Thu, 6 Aug 2026 17:24:04 -0400 Subject: [PATCH] preflight: stop ConvertFrom-Json choking on the driver catalogue The driver check - the most valuable check in this script - has never actually run. It died on: Driver check failed: Cannot convert the JSON string because a dictionary that was converted from the string contains the duplicated keys 'FileName' and 'FileName' HardwareDriver.json carries both casings of the same fields - fileName and FileName, destinationDir and DestinationDir. ConvertFrom-Json treats object keys case-insensitively and refuses the document. -AsHashtable would handle it but that is PowerShell 6+, and WinPE runs 5.1. Confirmed it throws on PowerShell 7 too, so no version of ConvertFrom-Json can read this file as-is. Pulls the four needed fields out of each entry by regex instead, preferring the lowercase key and falling back to the capitalised one, and unescaping the backslashes in destinationDir. Tested against the real 44-entry catalogue, all three outcomes: OptiPlex Micro 7020, pack present -> OK, win11_optiplexd13mlk7020_a09.zip same model, pack removed -> FAIL, names the missing path Surface Laptop 7 -> FAIL, no pack matches Worth noting the check was failing SAFE - a WARN that reads like a tooling glitch rather than a missing driver pack. It would have stayed invisible until a bay imaged with no NIC. --- playbook/scripts/preflight.ps1 | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/playbook/scripts/preflight.ps1 b/playbook/scripts/preflight.ps1 index a6ab3b3..825f006 100755 --- a/playbook/scripts/preflight.ps1 +++ b/playbook/scripts/preflight.ps1 @@ -81,7 +81,38 @@ try { if (-not (Test-Path $catalogue)) { Warn "HardwareDriver.json not found at $catalogue - cannot check drivers." } else { - $entries = Get-Content $catalogue -Raw | ConvertFrom-Json + # NOT ConvertFrom-Json. HardwareDriver.json carries both casings of the + # same fields - "fileName" and "FileName", "destinationDir" and + # "DestinationDir". Windows PowerShell 5.1 (which is what WinPE runs) + # treats object keys case-insensitively and throws: + # "cannot convert the JSON string because a dictionary that was + # converted from the string contains the duplicated keys 'FileName' + # and 'FileName'" + # -AsHashtable would handle it but that is PowerShell 6+. So pull the + # four fields we need out of each entry by text instead. Prefers the + # lowercase key, falls back to the capitalised one. + $raw = Get-Content $catalogue -Raw + $entries = @() + foreach ($chunk in ([regex]::Split($raw, '\}\s*,\s*\{'))) { + $get = { + param($names) + foreach ($n in $names) { + $m = [regex]::Match($chunk, '"' + $n + '"\s*:\s*"((?:[^"\\]|\\.)*)"') + if ($m.Success) { return $m.Groups[1].Value -replace '\\\\', '\' } + } + return '' + } + $e = [pscustomobject]@{ + modelswminame = (& $get @('modelswminame','models')) + family = (& $get @('family')) + fileName = (& $get @('fileName','FileName')) + destinationDir = (& $get @('destinationDir','DestinationDir')) + } + if ($e.modelswminame) { $entries += $e } + } + if (-not $entries.Count) { + Warn "Could not extract any entries from $catalogue - driver check skipped." + } $family = '' if ($model.ToUpper().Contains('LATITUDE')) { $family = 'Latitude' } if ($model.ToUpper().Contains('OPTIPLEX')) { $family = 'Optiplex' }