diff --git a/playbook/select-waxtrace-asset.ps1 b/playbook/select-waxtrace-asset.ps1 index 47b4b5c..28dfc97 100644 --- a/playbook/select-waxtrace-asset.ps1 +++ b/playbook/select-waxtrace-asset.ps1 @@ -27,7 +27,9 @@ function Read-BayList { param([string]$Path) if (-not (Test-Path -LiteralPath $Path)) { return @() } try { - return Import-Csv -LiteralPath $Path | Select-Object -Property asset_tag, unit_serial, probe_part + return Import-Csv -LiteralPath $Path | + Select-Object -Property asset_tag, unit_serial, probe_part | + Sort-Object -Property asset_tag -Descending } catch { return @() } diff --git a/playbook/shopfloor-setup/gea-shopfloor-waxtrace/09-Setup-WaxAndTrace.ps1 b/playbook/shopfloor-setup/gea-shopfloor-waxtrace/09-Setup-WaxAndTrace.ps1 index c207904..9112367 100644 --- a/playbook/shopfloor-setup/gea-shopfloor-waxtrace/09-Setup-WaxAndTrace.ps1 +++ b/playbook/shopfloor-setup/gea-shopfloor-waxtrace/09-Setup-WaxAndTrace.ps1 @@ -164,20 +164,76 @@ if (-not $asset) { Write-WTLog "Mounting cal ISO: $($candidate.FullName)" try { $img = Mount-DiskImage -ImagePath $candidate.FullName -PassThru -ErrorAction Stop - Start-Sleep -Seconds 2 - $calDrive = ($img | Get-Volume).DriveLetter - Write-WTLog " mounted at ${calDrive}:" - $calSetup = "${calDrive}:\Setup.exe" - if (Test-Path -LiteralPath $calSetup) { - Write-WTLog " running cal Setup.exe (may prompt - VB6 wrapper, same vintage as main installer)" - # Cal ISO Setup.exe is tiny (135KB) - if it prompts, user has to click through. - # Acceptable today; future: dark-deploy the data/*.txt files directly into - # the FormTracePak data dir + skip Setup.exe. - $p = Start-Process -FilePath $calSetup -WorkingDirectory "${calDrive}:\" -Wait -PassThru - Write-WTLog " cal Setup.exe exit $($p.ExitCode)" - } else { - Write-WTLog " cal Setup.exe not found on ISO at $calSetup" 'WARN' + Start-Sleep -Seconds 5 + $calDrive = (Get-DiskImage -ImagePath $candidate.FullName | Get-Volume).DriveLetter + $calRoot = "${calDrive}:\" + Write-WTLog " mounted at $calRoot" + + # Disc layout differs by probe series. We have observed two: + # + # Older 218-458A: E:\App.ini, E:\Setup.exe, E:\data\CVIFDLL.ini, + # E:\data\Cvif_Correction.exe, E:\data\.txt. + # Vendor Setup.exe works (VB6, may prompt). + # + # Newer 218-378-13: E:\setup.bat, E:\setup.exe (.NET 4.0), + # E:\iniStatus\, E:\data\cvifdll.ini, + # E:\data\.txt - BUT the filenames have a + # bug: probe ID ends with a TRAILING SPACE + # ("218-378-13 _100072210.txt"). The vendor's + # .NET Setup.exe calls FileSystemInfo.set_Attributes + # on the source path and throws System.ArgumentException + # because the path contains an embedded space + # component, crashing every time + # (exit -532462766 = 0xE0434352, .NET unhandled + # exception). See diag-cal.log, WER Event 1026. + # + # We bypass the vendor wrapper entirely when the disc carries + # the buggy filenames and do a direct file copy into FormTracePak's + # data dir, renaming each file to strip the trailing space. + $srcDataDir = Join-Path $calRoot 'data' + $dstDataDir = 'C:\Program Files (x86)\MitutoyoApp\Formtracepak\data' + + $hasBrokenFilenames = $false + if (Test-Path -LiteralPath $srcDataDir) { + $hasBrokenFilenames = [bool](Get-ChildItem -LiteralPath $srcDataDir -Filter '*[0-9] _*.txt' -ErrorAction SilentlyContinue | Select-Object -First 1) } + + if ($hasBrokenFilenames) { + Write-WTLog " disc has trailing-space probe-ID filenames (218-378-13 series) - bypassing buggy vendor Setup.exe, doing direct copy" + if (-not (Test-Path -LiteralPath $dstDataDir)) { + Write-WTLog " destination data dir does not exist: $dstDataDir" 'ERROR' + Write-WTLog " (FormTracePak install may not be complete; cal apply aborted)" 'ERROR' + } else { + $copied = 0 + Get-ChildItem -LiteralPath $srcDataDir -File -ErrorAction SilentlyContinue | ForEach-Object { + # Strip ' _' (space-underscore) -> '_' inside the filename to + # heal the Mitutoyo burn-time typo. cvifdll.ini etc unaffected. + $cleanName = $_.Name -replace ' _', '_' + $dst = Join-Path $dstDataDir $cleanName + try { + Copy-Item -LiteralPath $_.FullName -Destination $dst -Force -ErrorAction Stop + # Clear read-only on the destination so future overwrites work. + try { (Get-Item -LiteralPath $dst).Attributes = 'Normal' } catch {} + Write-WTLog " copied $($_.Name) -> $cleanName" + $copied++ + } catch { + Write-WTLog " copy failed for $($_.Name): $_" 'ERROR' + } + } + Write-WTLog " direct copy complete: $copied file(s) into $dstDataDir" + } + } else { + # Older-style disc (clean filenames). Vendor Setup.exe is reliable. + $calSetup = "${calDrive}:\Setup.exe" + if (Test-Path -LiteralPath $calSetup) { + Write-WTLog " running cal Setup.exe (may prompt - VB6 wrapper, same vintage as main installer)" + $p = Start-Process -FilePath $calSetup -WorkingDirectory $calRoot -Wait -PassThru + Write-WTLog " cal Setup.exe exit $($p.ExitCode)" + } else { + Write-WTLog " cal Setup.exe not found at $calSetup" 'WARN' + } + } + Dismount-DiskImage -ImagePath $candidate.FullName -ErrorAction SilentlyContinue | Out-Null Write-WTLog " cal ISO dismounted" } catch { diff --git a/playbook/shopfloor-setup/gea-shopfloor-waxtrace/select-waxtrace-asset.ps1 b/playbook/shopfloor-setup/gea-shopfloor-waxtrace/select-waxtrace-asset.ps1 new file mode 100644 index 0000000..28dfc97 --- /dev/null +++ b/playbook/shopfloor-setup/gea-shopfloor-waxtrace/select-waxtrace-asset.ps1 @@ -0,0 +1,102 @@ +# select-waxtrace-asset.ps1 - Arrow-key bay picker for wax/trace imaging. +# +# Reads the calibration INDEX.csv on the PXE share to build the menu of known +# bays. Operator picks with Up/Down arrows + Enter. Always appends an +# "Other (new bay)" option at the end for bays that don't have a cal ISO yet - +# selecting it falls back to a free-text prompt. +# +# Writes the chosen asset tag to $OutFile (one line, no trailing newline). +# startnet.cmd reads that file back into the MACHINENUM batch var. +# +# Runs in WinPE PowerShell. Win10/11 WinPE ships powershell.exe with +# System.Console.ReadKey support. Tested 2026-05-18. +# +# Exit codes: +# 0 = asset tag written to $OutFile +# 1 = user cancelled (Esc) - $OutFile not written +# 2 = INDEX.csv unreadable AND no fallback entered + +param( + [string]$IndexPath = 'Y:\installers-post\waxtrace\calibrations\INDEX.csv', + [Parameter(Mandatory=$true)][string]$OutFile +) + +$ErrorActionPreference = 'Continue' + +function Read-BayList { + param([string]$Path) + if (-not (Test-Path -LiteralPath $Path)) { return @() } + try { + return Import-Csv -LiteralPath $Path | + Select-Object -Property asset_tag, unit_serial, probe_part | + Sort-Object -Property asset_tag -Descending + } catch { + return @() + } +} + +function Show-Menu { + param( + [object[]]$Items, + [int]$Selected, + [string]$Title + ) + Clear-Host + Write-Host "" + Write-Host " ========================================" + Write-Host " $Title" + Write-Host " ========================================" + Write-Host "" + Write-Host " Up / Down arrows = navigate, Enter = select, Esc = cancel" + Write-Host "" + for ($i = 0; $i -lt $Items.Count; $i++) { + $item = $Items[$i] + $line = if ($item -is [string]) { $item } else { "{0,-10} serial={1,-12} probe={2}" -f $item.asset_tag, $item.unit_serial, $item.probe_part } + if ($i -eq $Selected) { + Write-Host (" > " + $line) -ForegroundColor Black -BackgroundColor White + } else { + Write-Host (" " + $line) + } + } + Write-Host "" +} + +$bays = @(Read-BayList -Path $IndexPath) +$menuItems = @() +foreach ($b in $bays) { $menuItems += $b } +$menuItems += '** Other (new bay - enter asset tag manually) **' + +$sel = 0 +while ($true) { + Show-Menu -Items $menuItems -Selected $sel -Title "Wax/Trace Asset Tag" + $key = [System.Console]::ReadKey($true) + switch ($key.Key) { + 'UpArrow' { if ($sel -gt 0) { $sel-- } } + 'DownArrow' { if ($sel -lt ($menuItems.Count - 1)) { $sel++ } } + 'Enter' { + if ($sel -eq ($menuItems.Count - 1)) { + # Manual entry + Write-Host "" + $manual = Read-Host " Enter asset tag (e.g. WJRP9999) or blank to abort" + if ($manual) { + $manual = $manual.Trim().ToUpper() + Set-Content -LiteralPath $OutFile -Value $manual -NoNewline -Encoding ascii + Write-Host "" + Write-Host " Saved asset tag: $manual" + Start-Sleep -Seconds 1 + exit 0 + } else { + exit 1 + } + } else { + $pick = $bays[$sel].asset_tag + Set-Content -LiteralPath $OutFile -Value $pick -NoNewline -Encoding ascii + Write-Host "" + Write-Host " Selected: $pick" + Start-Sleep -Seconds 1 + exit 0 + } + } + 'Escape' { exit 1 } + } +} diff --git a/playbook/shopfloor-setup/gea-shopfloor-waxtrace/waxtrace-manifest.json b/playbook/shopfloor-setup/gea-shopfloor-waxtrace/waxtrace-manifest.json index 81794fa..60f9e9d 100644 --- a/playbook/shopfloor-setup/gea-shopfloor-waxtrace/waxtrace-manifest.json +++ b/playbook/shopfloor-setup/gea-shopfloor-waxtrace/waxtrace-manifest.json @@ -25,26 +25,24 @@ "DetectionValue": "9.0.21022" }, { - "_comment": "Visual C++ 2017 x86 redist (14.15.26706 = VS2017 Update 7 era). Mitutoyo's vc_redist.x86.exe at Lang\\English\\ on the FormTracePak ISO. Uses VS2015+ universal redist installer flag set.", + "_comment": "Visual C++ 2017 x86 redist (Mitutoyo ships 14.15.26706 = VS2017 Update 7 era). Detection by key+name presence only, NOT exact version: Windows Update or other software routinely bumps VS14 runtime to 14.16+ or 14.3x+, and the older Mitutoyo redist refuses to install over the newer (exits non-zero) which the engine then marks as failed even though the runtime is fine. All VS14 / VC++ 2015-2022 redists are backward-compatible so any installed version satisfies FormTracePak.", "Name": "Microsoft Visual C++ 2017 Redistributable (x86)", "Installer": "prereqs\\vc_redist.x86.exe", "Type": "EXE", "InstallArgs": "/quiet /norestart", "DetectionMethod": "Registry", "DetectionPath": "HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x86", - "DetectionName": "Version", - "DetectionValue": "v14.15.26706" + "DetectionName": "Version" }, { - "_comment": "Visual C++ 2017 x64 redist.", + "_comment": "Visual C++ 2017 x64 redist. Same key+name-presence detection as x86 (see comment above).", "Name": "Microsoft Visual C++ 2017 Redistributable (x64)", "Installer": "prereqs\\vc_redist.x64.exe", "Type": "EXE", "InstallArgs": "/quiet /norestart", "DetectionMethod": "Registry", "DetectionPath": "HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\VisualStudio\\14.0\\VC\\Runtimes\\x64", - "DetectionName": "Version", - "DetectionValue": "v14.15.26706" + "DetectionName": "Version" }, { "_comment": "Sentinel Runtime / HASP USB dongle driver from Gemalto (now Thales). Vintage 2019 InstallShield wrapper, classic InstallShield silent install via /s + nested /v args. FormTracePak licensing is dongle-bound; the runtime + drivers must be present before Formtracepak.exe will run. Tech inserts physical HASP USB dongle on the bay post-imaging to license.", diff --git a/playbook/startnet.cmd b/playbook/startnet.cmd index 88f46d4..7a77356 100644 --- a/playbook/startnet.cmd +++ b/playbook/startnet.cmd @@ -189,13 +189,24 @@ echo Machine number: %MACHINENUM% goto skip_machinenum :prompt_waxtrace_asset echo. -echo Wax/Trace bays use the asset tag (e.g. WJRP2335) to pick the right -echo calibration ISO during shopfloor setup. -set /p MACHINENUM=Enter asset tag (e.g. WJRP2335): -if "%MACHINENUM%"=="" ( - echo WARNING: no asset tag entered - calibration apply will be skipped. - set MACHINENUM= -) +echo Loading Wax/Trace bay list from PXE share... +REM Mount enrollment share early so the picker can read INDEX.csv. Later +REM net use Y: will be a no-op if Y: is already mapped. +net use Y: \\172.16.9.1\enrollment /user:pxe-upload pxe /persistent:no >NUL 2>NUL +del X:\waxtrace-asset.txt 2>NUL +if not exist "Y:\installers-post\waxtrace\select-waxtrace-asset.ps1" goto waxtrace_picker_skip +powershell.exe -NoProfile -ExecutionPolicy Bypass -File "Y:\installers-post\waxtrace\select-waxtrace-asset.ps1" -IndexPath "Y:\installers-post\waxtrace\calibrations\INDEX.csv" -OutFile "X:\waxtrace-asset.txt" +:waxtrace_picker_skip +set MACHINENUM= +if exist X:\waxtrace-asset.txt set /p MACHINENUM=