Wax/Trace triad: arrow-key bay picker + S: backup path

Two operator-UX improvements for the Backup / Export / Install triad.

1. Backup target moves from \\tsgwp00525\...\formtracepac to S:\2 WJ Scans
   Record Retention\backup\waxtrace\<asset>\. S: is mapped at shopfloor
   imaging time and stays mapped post-categorization, so the same default
   path works whether the operator runs the backup on an old bay (manual
   pre-image capture) or a freshly imaged one. The destination directory
   is created if missing.

2. New Select-WaxtraceAsset.ps1 - arrow-key bay picker patterned after
   the WinPE select-waxtrace-asset.ps1. Reads bay-config.csv (sibling
   file), shows asset_tag + ftpak_version + model + user_id per row, and
   returns the selected asset_tag via stdout. Falls back to a manual
   entry prompt if the CSV is missing or the operator picks "Other".

   Backup / Export / Install now invoke the picker when interactive AND
   bay-config.csv is alongside the script. Non-interactive paths
   (qga / SYSTEM / scheduled task) keep silently defaulting to
   COMPUTERNAME so unattended runs are unchanged.

   Export gained an -AssetNumber parameter and stamps it into the output
   CSV filename so multiple inventories from the same host stay
   distinguishable when the operator is auditing several bays in a row.

bay-config.csv is copied into the scripts\ dir so the picker has a
source of truth that ships next to the scripts (and into pxe-images
for tech distribution).

Smoke tested on win11 VM: all four PS1 parse-clean, non-interactive
backup path still produces a valid ZIP (silent COMPUTERNAME default),
picker handles missing-CSV gracefully (manual-entry fallback). The
arrow-key UX itself is operator-verifiable only on a real terminal.
This commit is contained in:
cproudlock
2026-05-24 07:41:25 -04:00
parent a104cfdebb
commit b8bb00e2fe
5 changed files with 200 additions and 20 deletions

View File

@@ -16,13 +16,13 @@
Asset number (e.g. WJRP1234) used to namespace the backup on the shopfloor
share. If omitted, the script prompts interactively and defaults to the
current $env:COMPUTERNAME. The asset number is the leaf folder under
\\tsgwp00525.wjs.geaerospace.net\shared\DT\Shopfloor\backup\formtracepac\
S:\2 WJ Scans Record Retention\backup\waxtrace\
Ignored if -Destination is supplied.
.PARAMETER Destination
Where to write the ZIP file. Can be a USB drive, network share, or local path.
If omitted, defaults to the per-asset path on the GE shopfloor share:
\\tsgwp00525.wjs.geaerospace.net\shared\DT\Shopfloor\backup\formtracepac\<AssetNumber>
If omitted, defaults to the per-asset path on the mapped S: drive:
S:\2 WJ Scans Record Retention\backup\waxtrace\<AssetNumber>
The destination directory is created if it does not exist.
.PARAMETER NoZip
@@ -45,17 +45,30 @@ param(
[switch]$IncludeExecutables
)
$SharedRoot = '\\tsgwp00525.wjs.geaerospace.net\shared\DT\Shopfloor\backup\formtracepac'
$SharedRoot = 'S:\2 WJ Scans Record Retention\backup\waxtrace'
if (-not $Destination) {
if (-not $AssetNumber) {
$defaultAsset = $env:COMPUTERNAME
if ([Environment]::UserInteractive -and -not [Console]::IsInputRedirected) {
$input = Read-Host "Asset number for this backup (e.g. WJRP1234) [$defaultAsset]"
if ([string]::IsNullOrWhiteSpace($input)) {
$AssetNumber = $defaultAsset
} else {
$AssetNumber = $input.Trim()
# Prefer arrow-key picker against bay-config.csv if it is sitting
# next to this script. Falls through to a plain Read-Host prompt
# if no picker / no CSV available.
$picker = Join-Path $PSScriptRoot 'Select-WaxtraceAsset.ps1'
$cfg = Join-Path $PSScriptRoot 'bay-config.csv'
if ((Test-Path -LiteralPath $picker) -and (Test-Path -LiteralPath $cfg)) {
$picked = & $picker -ConfigCsv $cfg -Title 'Backup FormTracePak - pick the bay being captured'
if ($picked) {
$AssetNumber = $picked
}
}
if (-not $AssetNumber) {
$input = Read-Host "Asset number for this backup (e.g. WJRP1234) [$defaultAsset]"
if ([string]::IsNullOrWhiteSpace($input)) {
$AssetNumber = $defaultAsset
} else {
$AssetNumber = $input.Trim()
}
}
} else {
# Non-interactive (qga / SYSTEM / scheduled task): fall back to COMPUTERNAME silently.

View File

@@ -15,16 +15,46 @@
.PARAMETER ComputerName
Hostname to stamp on the inventory rows. Defaults to $env:COMPUTERNAME.
.PARAMETER AssetNumber
Asset number (e.g. WJRP1234) used in the output CSV filename so multiple
inventories from the same host stay distinguishable. If omitted, the script
prompts interactively (with arrow-key picker if bay-config.csv is alongside)
and defaults to $ComputerName non-interactively.
.EXAMPLE
.\Export-FormtracepakInventory.ps1
.\Export-FormtracepakInventory.ps1 -OutputPath "E:\inventories"
.\Export-FormtracepakInventory.ps1 -OutputPath "E:\inventories" -AssetNumber WJRP2335
#>
[CmdletBinding()]
param(
[string]$OutputPath = $PSScriptRoot,
[string]$ComputerName = $env:COMPUTERNAME
[string]$ComputerName = $env:COMPUTERNAME,
[string]$AssetNumber
)
if (-not $AssetNumber) {
if ([Environment]::UserInteractive -and -not [Console]::IsInputRedirected) {
$picker = Join-Path $PSScriptRoot 'Select-WaxtraceAsset.ps1'
$cfg = Join-Path $PSScriptRoot 'bay-config.csv'
if ((Test-Path -LiteralPath $picker) -and (Test-Path -LiteralPath $cfg)) {
$picked = & $picker -ConfigCsv $cfg -Title 'Inventory FormTracePak - pick the bay being audited'
if ($picked) {
$AssetNumber = $picked
}
}
if (-not $AssetNumber) {
$assetInput = Read-Host "Asset number to stamp on inventory (e.g. WJRP1234) [$ComputerName]"
if ([string]::IsNullOrWhiteSpace($assetInput)) {
$AssetNumber = $ComputerName
} else {
$AssetNumber = $assetInput.Trim()
}
}
} else {
$AssetNumber = $ComputerName
}
}
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Continue'
@@ -98,7 +128,7 @@ $MitutoyoFileExtensions = @(
# ----------------------------------------------------------------------
$timestamp = Get-Date -Format 'yyyyMMdd_HHmmss'
$csvFile = Join-Path $OutputPath "formtracepak_inventory_${ComputerName}_${timestamp}.csv"
$csvFile = Join-Path $OutputPath "formtracepak_inventory_${AssetNumber}_${ComputerName}_${timestamp}.csv"
$inventory = [System.Collections.Generic.List[PSObject]]::new()
function Add-Item {

View File

@@ -20,8 +20,8 @@
.PARAMETER BackupPath
Path to the backup ZIP, directory containing a backup ZIP, or already-extracted
backup folder created by Backup-FormtracepakSettings.ps1. If omitted, defaults
to the per-asset path on the GE shopfloor share:
\\tsgwp00525.wjs.geaerospace.net\shared\DT\Shopfloor\backup\formtracepac\<AssetNumber>
to the per-asset path on the mapped S: drive:
S:\2 WJ Scans Record Retention\backup\waxtrace\<AssetNumber>
If the path is a directory, the newest formtracepak_backup_*.zip inside it is used.
.PARAMETER RestoreRegistry
@@ -60,17 +60,28 @@ param(
[switch]$Force
)
$SharedRoot = '\\tsgwp00525.wjs.geaerospace.net\shared\DT\Shopfloor\backup\formtracepac'
$SharedRoot = 'S:\2 WJ Scans Record Retention\backup\waxtrace'
if (-not $BackupPath) {
if (-not $AssetNumber) {
$defaultAsset = $env:COMPUTERNAME
if ([Environment]::UserInteractive -and -not [Console]::IsInputRedirected) {
$assetInput = Read-Host "Asset number to restore (e.g. WJRP1234) [$defaultAsset]"
if ([string]::IsNullOrWhiteSpace($assetInput)) {
$AssetNumber = $defaultAsset
} else {
$AssetNumber = $assetInput.Trim()
# Prefer arrow-key picker against bay-config.csv if available.
$picker = Join-Path $PSScriptRoot 'Select-WaxtraceAsset.ps1'
$cfg = Join-Path $PSScriptRoot 'bay-config.csv'
if ((Test-Path -LiteralPath $picker) -and (Test-Path -LiteralPath $cfg)) {
$picked = & $picker -ConfigCsv $cfg -Title 'Restore FormTracePak - pick the bay being restored'
if ($picked) {
$AssetNumber = $picked
}
}
if (-not $AssetNumber) {
$assetInput = Read-Host "Asset number to restore (e.g. WJRP1234) [$defaultAsset]"
if ([string]::IsNullOrWhiteSpace($assetInput)) {
$AssetNumber = $defaultAsset
} else {
$AssetNumber = $assetInput.Trim()
}
}
} else {
$AssetNumber = $defaultAsset

View File

@@ -0,0 +1,110 @@
<#
.SYNOPSIS
Arrow-key bay picker for Wax/Trace Export / Backup / Install scripts.
.DESCRIPTION
Reads bay-config.csv (asset_tag,ftpak_version,model,user_id) and presents
an Up/Down picker. Returns the chosen asset_tag to stdout so the calling
script can capture it. Always appends an "Other (manual entry)" option.
Same UX as the WinPE select-waxtrace-asset.ps1 used by startnet.cmd.
Distinct from that script because it returns the asset tag via stdout
rather than writing to a file, and presents the richer per-bay columns
(FTPak version + model + USER ID) from bay-config.csv.
.PARAMETER ConfigCsv
Path to bay-config.csv. Defaults to a sibling file next to this script.
.PARAMETER Title
Header text shown above the picker. Defaults to "Wax/Trace Asset".
.OUTPUTS
String. The chosen asset_tag, printed to stdout. Empty string on cancel.
.EXAMPLE
$asset = & .\Select-WaxtraceAsset.ps1
$asset = & .\Select-WaxtraceAsset.ps1 -ConfigCsv 'C:\foo\bay-config.csv' -Title 'Pick bay to back up'
#>
[CmdletBinding()]
param(
[string]$ConfigCsv = (Join-Path $PSScriptRoot 'bay-config.csv'),
[string]$Title = 'Wax/Trace Asset'
)
$ErrorActionPreference = 'Continue'
function Read-BayList {
param([string]$Path)
if (-not (Test-Path -LiteralPath $Path)) { return @() }
try {
return Import-Csv -LiteralPath $Path |
Sort-Object -Property asset_tag
} 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 ''
Write-Host (' {0,-10} {1,-8} {2,-10} {3}' -f 'ASSET', 'FTPAK', 'MODEL', 'USER ID')
Write-Host (' {0,-10} {1,-8} {2,-10} {3}' -f '-----', '-----', '-----', '-------')
for ($i = 0; $i -lt $Items.Count; $i++) {
$item = $Items[$i]
if ($item -is [string]) {
$line = $item
} else {
$line = '{0,-10} {1,-8} {2,-10} {3}' -f $item.asset_tag, $item.ftpak_version, $item.model, $item.user_id
}
if ($i -eq $Selected) {
Write-Host (' > ' + $line) -ForegroundColor Black -BackgroundColor White
} else {
Write-Host (' ' + $line)
}
}
Write-Host ''
}
$bays = @(Read-BayList -Path $ConfigCsv)
$menuItems = @()
foreach ($b in $bays) { $menuItems += $b }
$menuItems += '** Other (enter asset tag manually) **'
if ($menuItems.Count -eq 1) {
# Only the manual-entry sentinel: CSV missing or unparseable. Fall back
# to a plain prompt rather than wedging the operator in an empty menu.
Write-Host " (bay-config.csv not readable at $ConfigCsv - falling back to manual entry)"
$manual = Read-Host " Enter asset tag (e.g. WJRP9999) or blank to abort"
if ($manual) { return $manual.Trim().ToUpper() } else { return '' }
}
$sel = 0
while ($true) {
Show-Menu -Items $menuItems -Selected $sel -Title $Title
$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)) {
Write-Host ''
$manual = Read-Host ' Enter asset tag (e.g. WJRP9999) or blank to abort'
if ($manual) {
return $manual.Trim().ToUpper()
} else {
return ''
}
} else {
return $bays[$sel].asset_tag
}
}
'Escape' { return '' }
}
}

View File

@@ -0,0 +1,16 @@
asset_tag,ftpak_version,model,user_id
WJF00159,6.103,AVANT,3974839712
WJRP3689,5.510,CV-4500,3744284509
WJRP2660,6.0,CV-4500,2365986521
WJRP2659,6.0,CV-4500,2709054503
WJF00545,6.213,AVANT,3878777362
WJRP3638,5.602,CV-4500,0720778210
WJF00052,6.103,AVANT,3270314998
WJF00084,6.103,AVANT,1476212857
WJF00083,6.103,AVANT,2934506987
WJRP3025,6.0,CV-3200,2292822471
WJF00197,6.104,AVANT,1191612605
WJRP4802,6.002,AVANT,0920866935
WJRP2347,6.0,CV-4500,3585172946
WJRP2035,6.0,CV-4500,2292822471
WJRP2335,6.0,CV-4500,1780916688
1 asset_tag ftpak_version model user_id
2 WJF00159 6.103 AVANT 3974839712
3 WJRP3689 5.510 CV-4500 3744284509
4 WJRP2660 6.0 CV-4500 2365986521
5 WJRP2659 6.0 CV-4500 2709054503
6 WJF00545 6.213 AVANT 3878777362
7 WJRP3638 5.602 CV-4500 0720778210
8 WJF00052 6.103 AVANT 3270314998
9 WJF00084 6.103 AVANT 1476212857
10 WJF00083 6.103 AVANT 2934506987
11 WJRP3025 6.0 CV-3200 2292822471
12 WJF00197 6.104 AVANT 1191612605
13 WJRP4802 6.002 AVANT 0920866935
14 WJRP2347 6.0 CV-4500 3585172946
15 WJRP2035 6.0 CV-4500 2292822471
16 WJRP2335 6.0 CV-4500 1780916688