diff --git a/playbook/shopfloor-setup/Shopfloor/06-OrganizeDesktop.ps1 b/playbook/shopfloor-setup/Shopfloor/06-OrganizeDesktop.ps1 index 680f431..2640731 100644 --- a/playbook/shopfloor-setup/Shopfloor/06-OrganizeDesktop.ps1 +++ b/playbook/shopfloor-setup/Shopfloor/06-OrganizeDesktop.ps1 @@ -330,7 +330,16 @@ function Add-ShopfloorToolsApps { # Kind = 'existing' -> copy an existing .lnk via Find-ExistingLnk $cfgApps = Get-ProfileValue 'desktopApps' - if ($null -ne $cfgApps -and $cfgApps.Count -gt 0) { + # An EMPTY configured list means "no desktop apps" and must be honoured. + # Get-ProfileValue returns $null only when the key is absent from both the + # profile and site-config, so $null is the real "not configured" signal. + # + # The old test also required .Count -gt 0, which meant "desktopApps": [] + # fell through to the hardcoded shopfloor list below - so a Display kiosk, + # which explicitly configures an empty list, was given UDC, eDNC, NTLARS, + # WJ Shopfloor and Defect_Tracker shortcuts. Configuring "none" produced + # "everything". Observed on 579C144, 2026-08-06. + if ($null -ne $cfgApps) { $apps = @($cfgApps | ForEach-Object { $entry = @{ Name = $_.name; Kind = $_.kind } if ($_.kind -eq 'exe') { $entry.ExePath = $_.exePath } @@ -556,6 +565,9 @@ if (Test-Path -LiteralPath $overridesPath) { $cfgStartup = Get-ProfileValue 'startupItems' +# Same rule as desktopApps: $null = not configured, empty array = configured as +# none. Harmless here today because the else branch has no hardcoded fallback, +# but kept consistent so the two keys cannot drift apart again. if ($null -ne $cfgStartup -and $cfgStartup.Count -gt 0) { if (-not (Test-Path $startupDir)) { New-Item -ItemType Directory -Path $startupDir -Force | Out-Null diff --git a/playbook/shopfloor-setup/Shopfloor/Register-CheckMachineNumberTask.ps1 b/playbook/shopfloor-setup/Shopfloor/Register-CheckMachineNumberTask.ps1 index 5e635b1..2bb3069 100644 --- a/playbook/shopfloor-setup/Shopfloor/Register-CheckMachineNumberTask.ps1 +++ b/playbook/shopfloor-setup/Shopfloor/Register-CheckMachineNumberTask.ps1 @@ -50,6 +50,36 @@ try { } } catch { Write-RegLog "Could not unregister legacy '$oldTaskName': $_" } +# PC types that have no machine number by design. Arming the prompt on these +# guarantees a dialog nobody can answer: startnet only collects a machine number +# for the machine-tool types, so everything else is left on the 9999 placeholder +# and the check below would otherwise fire on every one of them. +# +# Observed on 579C144 (a Display) 2026-08-06: PreInstall logged +# "Machine number: 9999 (default placeholder)" and the logon prompt armed itself +# on a kiosk with no keyboard. +$noMachineNumberTypes = @( + 'gea-shopfloor-display' +) +$pcTypeFile = 'C:\Enrollment\pc-type.txt' +$pcType = '' +if (Test-Path -LiteralPath $pcTypeFile) { + $pcType = (Get-Content -LiteralPath $pcTypeFile -First 1 -ErrorAction SilentlyContinue) + if ($pcType) { $pcType = $pcType.Trim() } +} +if ($pcType -and ($noMachineNumberTypes -contains $pcType)) { + Write-RegLog "PC type '$pcType' has no machine number by design. Not registering the prompt." + foreach ($t in @($promptTaskName, $applyTaskName)) { + try { + if (Get-ScheduledTask -TaskName $t -ErrorAction SilentlyContinue) { + Unregister-ScheduledTask -TaskName $t -Confirm:$false -ErrorAction Stop + Write-RegLog "Unregistered stale task '$t'" + } + } catch {} + } + return +} + # Only arm the tasks if the bay was imaged with the 9999 placeholder. If # the tech entered a real machine number during PXE imaging it's already # in C:\Enrollment\machine-number.txt; no prompt needed on first logon. diff --git a/playbook/shopfloor-setup/Shopfloor/Register-MapSfldShare.ps1 b/playbook/shopfloor-setup/Shopfloor/Register-MapSfldShare.ps1 index 3a94c2c..139fbb6 100644 --- a/playbook/shopfloor-setup/Shopfloor/Register-MapSfldShare.ps1 +++ b/playbook/shopfloor-setup/Shopfloor/Register-MapSfldShare.ps1 @@ -16,6 +16,42 @@ $ErrorActionPreference = 'Continue' +# PC types that are self-contained and must NOT map S:. A Display kiosk is +# Entra-joined with local accounts and no SFLD credentials, so the mapping can +# only ever fail - once per logon, forever. +# +# Run-ShopfloorSetup.ps1 already gates the CALL to this script on the same list, +# but on 579C144 (2026-08-06) the Run entry was registered on a Display anyway: +# +# [15:07:55] Set HKLM:\...\Run\GE Map SFLD Share = ...Map-SfldShare.ps1 +# +# with no "Skipping S: drive logon mapper" in the log, so something in the +# finalization phase reaches this script past the call-site gate. Gating here as +# well makes the outcome correct regardless of who invokes it. +$selfContainedTypes = @('Display', 'gea-shopfloor-display') +$pcTypeFile = 'C:\Enrollment\pc-type.txt' +$pcType = '' +if (Test-Path -LiteralPath $pcTypeFile) { + $pcType = (Get-Content -LiteralPath $pcTypeFile -First 1 -ErrorAction SilentlyContinue) + if ($pcType) { $pcType = $pcType.Trim() } +} +if ($pcType -and ($selfContainedTypes -contains $pcType)) { + $d = 'C:\Logs\SFLD' + if (-not (Test-Path $d)) { New-Item -ItemType Directory -Path $d -Force -EA SilentlyContinue | Out-Null } + Add-Content -Path (Join-Path $d 'register-mapshare.log') -EA SilentlyContinue ` + -Value ("[{0}] [INFO] PC type '{1}' is self-contained - not registering the S: mapper." -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $pcType) + Write-Host "PC type '$pcType' is self-contained - skipping S: drive mapper." + # Remove a stale entry from an earlier image or an earlier code path. + try { + $runKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run' + if ((Get-ItemProperty -Path $runKey -Name 'GE Map SFLD Share' -EA SilentlyContinue)) { + Remove-ItemProperty -Path $runKey -Name 'GE Map SFLD Share' -Force -EA Stop + Write-Host " removed stale 'GE Map SFLD Share' Run entry." + } + } catch { } + return +} + $installRoot = 'C:\Program Files\GE\SfldShare' $mapScript = Join-Path $installRoot 'Map-SfldShare.ps1' $logDir = 'C:\Logs\SFLD'