09-Setup-WaxAndTrace.ps1 Step 3: - Detect Mitutoyo's burn-time typo on 218-378-13 series cal discs (filenames carry a trailing space inside the probe ID component, e.g. "Linear_X_218-378-13 _100072210.txt"). Their own .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 cal apply on 218-378-13 bays (exit -532462766 = 0xE0434352, .NET unhandled exception). Confirmed via WER Event 1026 captured during today's WJF00159 imaging. - When the buggy filenames are detected, bypass the broken vendor Setup.exe and direct-copy data\*.* into C:\Program Files (x86)\MitutoyoApp\Formtracepak\data\, renaming each file to strip ' _' (space-underscore) -> '_'. Clear read-only attr on each landed file. Older 218-458A discs have clean filenames and still use the vendor Setup.exe path. waxtrace-manifest.json: - Drop DetectionValue=v14.15.26706 from both VC++ 2017 redist entries. Windows Update routinely bumps the VS14 runtime to 14.16+ / 14.3x+, the older Mitutoyo redist refuses to install over the newer (exit 1638 'Another version already installed') and the manifest engine marked it as failed even though the runtime was fine. Detection is now by registry-key+name presence, which any VC++ 2015-2022 redist satisfies (they are backward-compatible). startnet.cmd:prompt_waxtrace_asset: - Replace free-text input with select-waxtrace-asset.ps1 arrow-key picker driven from installers-post/waxtrace/calibrations/INDEX.csv. - Map Y: enrollment share early so the picker can read INDEX.csv. - Replace parens-in-parens block (echo of '(e.g. WJRP2335)' inside the if-paren caused 'to was unexpected at this time' parse error observed by tech mid-imaging) with goto-flow. - Fall back to free-text prompt if picker unavailable or operator presses Esc. select-waxtrace-asset.ps1: - Sort bays descending by asset tag so WJRP* lands at top of menu. - Also staged as gea-shopfloor-waxtrace/select-waxtrace-asset.ps1 so sync-waxtrace.sh ships it to installers-post/waxtrace/ on the share. sync-waxtrace.sh: - Push select-waxtrace-asset.ps1 next to INDEX.csv on the share. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
267 lines
14 KiB
PowerShell
267 lines
14 KiB
PowerShell
# 09-Setup-WaxAndTrace.ps1 - Wax and Trace pc-type setup (Mitutoyo FormTracePak v6.213)
|
|
#
|
|
# Imaging-time install. Installs prereqs from manifest, then runs the
|
|
# Mitutoyo FormTracePak v6.213 vendor installer from a mounted ISO. The
|
|
# VB6 Setup.exe wrapper checks GetDriveType() == DRIVE_CDROM; Mount-DiskImage
|
|
# satisfies that (a real CD drive isn't required). Per-asset calibration ISO
|
|
# applies last.
|
|
#
|
|
# Layout at C:\WaxTrace-Install\ (xcopied by startnet.cmd):
|
|
# waxtrace-manifest.json
|
|
# 09-Setup-WaxAndTrace.ps1 (this file)
|
|
# prereqs\vcredist_x86.exe (VC++ 2008 x86)
|
|
# prereqs\vcredist_x64.exe (VC++ 2008 x64)
|
|
# prereqs\vc_redist.x86.exe (VC++ 2017 x86)
|
|
# prereqs\vc_redist.x64.exe (VC++ 2017 x64)
|
|
# prereqs\HASPUserSetup.exe (Sentinel Runtime / HASP dongle driver)
|
|
# formtracepak\FORMTRACEPAK-V6.213.iso (vendor installer ISO, ~2 GB)
|
|
# calibrations\CAL-<asset>_serial-<sn>_probe-<probe>.iso (per-machine)
|
|
#
|
|
# Per-machine calibration is applied separately (mount cal ISO + run its
|
|
# Setup.exe), keyed by C:\Enrollment\machine-number.txt.
|
|
#
|
|
# Legacy captured/ replay path (V6.0 zip + reg) retired 2026-05-21. The
|
|
# captured-binary/ payload is still in the repo as a fallback - if the
|
|
# v6.213 vendor install fails on a bay, fall back to the captured path
|
|
# manually. See git history for the prior shape.
|
|
#
|
|
# Log: C:\Logs\WaxTrace\09-Setup-WaxAndTrace.log
|
|
# C:\Logs\WaxTrace\install.log (written by Install-FromManifest)
|
|
|
|
$ErrorActionPreference = 'Continue'
|
|
|
|
# Mirror the CMM pattern (09-Setup-CMM.ps1): the script itself lives in the
|
|
# shopfloor-setup tree (xcopied during WinPE), but the bulky bootstrap bundle
|
|
# (prereqs + captured master + cal ISOs) lives at C:\WaxTrace-Install\, put
|
|
# there by startnet.cmd from Y:\installers-post\waxtrace\ at imaging time.
|
|
$stagingRoot = 'C:\WaxTrace-Install'
|
|
$manifestPath = Join-Path $stagingRoot 'waxtrace-manifest.json'
|
|
$libSource = Join-Path $PSScriptRoot '..\common\lib\Install-FromManifest.ps1'
|
|
|
|
$logDir = 'C:\Logs\WaxTrace'
|
|
$installLog = Join-Path $logDir 'install.log'
|
|
$transcriptLog = Join-Path $logDir '09-Setup-WaxAndTrace.log'
|
|
|
|
if (-not (Test-Path $logDir)) {
|
|
New-Item -Path $logDir -ItemType Directory -Force | Out-Null
|
|
}
|
|
|
|
try { Start-Transcript -Path $transcriptLog -Append -Force | Out-Null } catch {}
|
|
|
|
function Write-WTLog {
|
|
param([string]$Message, [string]$Level = 'INFO')
|
|
$stamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
Write-Host "[$stamp] [$Level] $Message"
|
|
}
|
|
|
|
Write-WTLog "================================================================"
|
|
Write-WTLog "=== WaxTrace Setup (imaging-time) session start (PID $PID) ==="
|
|
Write-WTLog "Running as: $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)"
|
|
Write-WTLog "Script root: $PSScriptRoot"
|
|
Write-WTLog "================================================================"
|
|
|
|
# Status push - best-effort.
|
|
$pxeStatusLib = Join-Path $PSScriptRoot '..\Shopfloor\lib\Send-PxeStatus.ps1'
|
|
if (Test-Path $pxeStatusLib) {
|
|
try { . $pxeStatusLib; Send-PxeStatus -Stage '09-Setup-WaxAndTrace: starting' -StageIndex 3 -StageTotal 8 } catch { }
|
|
}
|
|
|
|
foreach ($file in @('pc-type.txt','machine-number.txt')) {
|
|
$path = "C:\Enrollment\$file"
|
|
if (Test-Path -LiteralPath $path) {
|
|
$content = (Get-Content -LiteralPath $path -First 1 -ErrorAction SilentlyContinue).Trim()
|
|
Write-WTLog " $file = $content"
|
|
} else {
|
|
Write-WTLog " $file = (not present)"
|
|
}
|
|
}
|
|
|
|
# ============================================================================
|
|
# Step 1: Prereqs via manifest (VC++ 2008 + 2017, HASP/Sentinel)
|
|
# ============================================================================
|
|
if (-not (Test-Path $manifestPath)) {
|
|
Write-WTLog "waxtrace-manifest.json not found at $manifestPath" 'ERROR'
|
|
} elseif (-not (Test-Path $libSource)) {
|
|
Write-WTLog "Install-FromManifest.ps1 not found at $libSource" 'ERROR'
|
|
} else {
|
|
Write-WTLog "Running Install-FromManifest (InstallerRoot=$PSScriptRoot)"
|
|
& $libSource -ManifestPath $manifestPath -InstallerRoot $stagingRoot -LogFile $installLog
|
|
$rc = $LASTEXITCODE
|
|
Write-WTLog "Install-FromManifest returned $rc"
|
|
}
|
|
|
|
# ============================================================================
|
|
# Step 2: FormTracePak v6.213 vendor install (Mount-DiskImage + Setup.exe)
|
|
# ============================================================================
|
|
# Detection: skip if Formtracepak already present (re-run safe).
|
|
$ftpakExe = 'C:\Program Files (x86)\MitutoyoApp\Formtracepak\Formtracepak.exe'
|
|
if (Test-Path -LiteralPath $ftpakExe) {
|
|
Write-WTLog "Formtracepak.exe already present - skipping vendor install"
|
|
} else {
|
|
$ftpakIso = Join-Path $stagingRoot 'formtracepak\FORMTRACEPAK-V6.213.iso'
|
|
if (-not (Test-Path -LiteralPath $ftpakIso)) {
|
|
Write-WTLog "FormTracePak ISO not found at $ftpakIso" 'ERROR'
|
|
} else {
|
|
Write-WTLog "Mounting FormTracePak ISO: $ftpakIso"
|
|
try {
|
|
$img = Mount-DiskImage -ImagePath $ftpakIso -PassThru -ErrorAction Stop
|
|
Start-Sleep -Seconds 8
|
|
$vol = Get-DiskImage -ImagePath $ftpakIso | Get-Volume
|
|
$ftpakDrive = $vol.DriveLetter
|
|
if (-not $ftpakDrive) {
|
|
Write-WTLog " Mount succeeded but no drive letter assigned" 'ERROR'
|
|
} else {
|
|
Write-WTLog " mounted at ${ftpakDrive}: (volume label=$($vol.FileSystemLabel))"
|
|
$setupExe = "${ftpakDrive}:\Setup.exe"
|
|
if (-not [System.IO.File]::Exists($setupExe)) {
|
|
Write-WTLog " Setup.exe not found at $setupExe" 'ERROR'
|
|
} else {
|
|
Write-WTLog " running $setupExe (VB6 wrapper - requires DRIVE_CDROM)"
|
|
# Setup.exe is the VB6 wrapper. /silent + /qn flags often
|
|
# ignored - the wrapper drives appSetup.exe + msiexec from
|
|
# its own UI. If the wrapper insists on interactive, a tech
|
|
# at the bay clicks through. Acceptable today; quieter
|
|
# path is a future improvement (drive msiexec direct on
|
|
# the wrapper's bundled MSIs).
|
|
try {
|
|
$p = Start-Process -FilePath $setupExe `
|
|
-WorkingDirectory "${ftpakDrive}:\" `
|
|
-ArgumentList '/silent' `
|
|
-Wait -PassThru
|
|
Write-WTLog " Setup.exe exit $($p.ExitCode)"
|
|
} catch {
|
|
Write-WTLog " Setup.exe failed: $_" 'ERROR'
|
|
}
|
|
}
|
|
}
|
|
Dismount-DiskImage -ImagePath $ftpakIso -ErrorAction SilentlyContinue | Out-Null
|
|
Write-WTLog " FormTracePak ISO dismounted"
|
|
} catch {
|
|
Write-WTLog " Mount-DiskImage failed: $_" 'ERROR'
|
|
}
|
|
}
|
|
}
|
|
|
|
# ============================================================================
|
|
# Step 3: Per-machine calibration ISO (mount + apply via cal Setup.exe)
|
|
# ============================================================================
|
|
# Cal ISOs are keyed by asset_tag. Read machine-number.txt to pick the right
|
|
# ISO. Each cal ISO is ~1.7MB and contains a tiny Mitutoyo wrapper Setup.exe
|
|
# plus data/*.txt compensation tables for the bay's specific probe + serial.
|
|
$mnPath = 'C:\Enrollment\machine-number.txt'
|
|
$asset = $null
|
|
if (Test-Path -LiteralPath $mnPath) {
|
|
$asset = (Get-Content -LiteralPath $mnPath -First 1 -ErrorAction SilentlyContinue).Trim()
|
|
}
|
|
if (-not $asset) {
|
|
Write-WTLog "machine-number.txt missing or empty - skipping calibration apply" 'WARN'
|
|
} else {
|
|
$calDir = Join-Path $stagingRoot 'calibrations'
|
|
$candidate = Get-ChildItem $calDir -Filter "CAL-${asset}_*.iso" -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
if (-not $candidate) {
|
|
Write-WTLog "No cal ISO matched CAL-${asset}_*.iso in $calDir - skipping" 'WARN'
|
|
} else {
|
|
Write-WTLog "Mounting cal ISO: $($candidate.FullName)"
|
|
try {
|
|
$img = Mount-DiskImage -ImagePath $candidate.FullName -PassThru -ErrorAction Stop
|
|
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\<files>.txt.
|
|
# Vendor Setup.exe works (VB6, may prompt).
|
|
#
|
|
# Newer 218-378-13: E:\setup.bat, E:\setup.exe (.NET 4.0),
|
|
# E:\iniStatus\<png>, E:\data\cvifdll.ini,
|
|
# E:\data\<files>.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 {
|
|
Write-WTLog " Mount-DiskImage failed: $_" 'ERROR'
|
|
}
|
|
}
|
|
}
|
|
|
|
# ============================================================================
|
|
# Step 4: OpenText auto-start at login (HostExplorer "WJ Shopfloor" session)
|
|
# ============================================================================
|
|
$autoStartLib = Join-Path $PSScriptRoot '..\Shopfloor\lib\Set-OpenTextAutoStart.ps1'
|
|
if (Test-Path -LiteralPath $autoStartLib) {
|
|
Write-WTLog "Calling $autoStartLib"
|
|
& $autoStartLib
|
|
} else {
|
|
Write-WTLog "Set-OpenTextAutoStart.ps1 not found at $autoStartLib - OpenText auto-start NOT configured" 'WARN'
|
|
}
|
|
|
|
if (Get-Command Send-PxeStatus -ErrorAction SilentlyContinue) {
|
|
$finalStatus = if ($rc -eq 0) { 'in_progress' } else { 'failed' }
|
|
$finalErr = if ($rc -ne 0) { "Install-FromManifest exit $rc" } else { '' }
|
|
Send-PxeStatus -Stage '09-Setup-WaxAndTrace: complete' -StageIndex 4 -StageTotal 8 -Status $finalStatus -Error_ $finalErr
|
|
}
|
|
|
|
Write-WTLog "================================================================"
|
|
Write-WTLog "=== WaxTrace Setup session end ==="
|
|
Write-WTLog "================================================================"
|
|
|
|
try { Stop-Transcript | Out-Null } catch {}
|