Phase 3+4 rename reorg: repo dir renames + startnet.cmd menu

Pairs with Phase 1+2 from earlier (alias maps in Install-FromManifest,
GE-Enforce, Get-PCProfile, verify-state). See project-shopfloor-rename-reorg
memory for the plan.

Phase 3 (repo + paths):
- git mv per-PC-type dirs to gea-shopfloor-* names:
    Standard      -> gea-shopfloor-collections
    CMM           -> gea-shopfloor-cmm
    Keyence       -> gea-shopfloor-keyence
    Genspect      -> gea-shopfloor-genspect
    WaxAndTrace   -> gea-shopfloor-waxtrace
    Display       -> gea-shopfloor-display
    Lab           -> gea-shopfloor-common (folded; Timeclock+Lab merge)
- New gea-shopfloor-nocollections/ (clone of collections sans UDC scripts).
- New gea-shopfloor-heattreat/ (placeholder, README only).
- Move Standard/ntlars-backups/ -> _ntlars-backups/ (per-MN, not per-type).
- Run-ShopfloorSetup.ps1: Resolve-PCTypeDir helper walks alias group when
  the on-disk dir for the current pcType is missing. Set-MachineNumber
  helper-copy gated on collections|nocollections|legacy Standard-Machine.
- Update-MachineNumber.ps1: pcProfiles lookups try gea-shopfloor-collections
  first, fall back to legacy Standard-Machine. PowerShell 5.1 compatible
  (no null-coalesce).

Phase 4 (startnet.cmd menu):
- Choice 3 "GEA Shopfloor" now drills into a 9-item sub-menu instead of
  going straight to enrollment. Sub-cats:
    1. Machine with Collections        -> gea-shopfloor-collections
    2. Machine without Collections     -> gea-shopfloor-nocollections
    3. Common (Timeclock, Lab)         -> gea-shopfloor-common
    4. Keyence                         -> gea-shopfloor-keyence
    5. CMM                             -> gea-shopfloor-cmm
    6. Genspect                        -> gea-shopfloor-genspect
    7. Heattreat                       -> gea-shopfloor-heattreat
    8. Wax and Trace                   -> gea-shopfloor-waxtrace
    9. Display                         -> gea-shopfloor-display
- Office menu (existing 6-option) follows for every sub-cat.
- Machine number prompt only for collections + nocollections.
- pc-subtype.txt + display-type.txt no longer written. PCTYPE is a
  single full string (gea-shopfloor-*); subtype-aware code paths fall
  back to empty and resolve via the alias map.
- CMM bootstrap stage gate switched from "%PCTYPE%"=="CMM" to
  "%PCTYPE%"=="gea-shopfloor-cmm".

Test harness:
- B-enforce/run.sh PCSUBTYPE default changed from "Machine" to "" so
  single-arg invocation matches the new single-string scheme. Two-arg
  legacy form ("Standard Machine") still works via aliasing.
- B-enforce/tamper.ps1 alias-aware Test-MatrixEntryMatches mirroring
  verify-state.ps1.

Smoke-tested on win11 VM as SYSTEM via qga: B-enforce harness 5-phase
cycle (stage / baseline / tamper / heal / idempotent) passes 10/10
with PCType=gea-shopfloor-collections AND with legacy "Standard Machine"
two-arg form.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
cproudlock
2026-05-04 08:09:16 -04:00
parent 48e20a7e73
commit 6dcf96e40a
262 changed files with 592 additions and 455 deletions

View File

@@ -0,0 +1,76 @@
# 09-Setup-Keyence.ps1 - Keyence type setup (runs during shopfloor-setup phase).
#
# Performs the imaging-time install of Keyence VR-6000 Series Software MSI +
# KEYENCE VR Series USB driver from the staged bundle. Ongoing enforcement
# is handled by GE-Enforce (registered separately in Run-ShopfloorSetup.ps1)
# reading keyence/manifest.json from the tsgwp00525 share.
#
# Layout at $PSScriptRoot (xcopied by startnet.cmd only for PCTYPE=Keyence):
# keyence-manifest.json
# 09-Setup-Keyence.ps1 (this file)
# installers\VR-6000 Series Software.msi
# drivers\keyence_vr_series.inf (+ cat + amd64\{Wdf,WinUsb}CoInstaller*.dll)
#
# Library lookup: the imaging-time install uses the common Install-FromManifest
# library at ..\common\lib\Install-FromManifest.ps1 (relative to $PSScriptRoot).
#
# Log: C:\Logs\Keyence\09-Setup-Keyence.log
# C:\Logs\Keyence\install.log (written by Install-FromManifest)
$ErrorActionPreference = 'Continue'
$manifestPath = Join-Path $PSScriptRoot 'keyence-manifest.json'
$libSource = Join-Path $PSScriptRoot '..\common\lib\Install-FromManifest.ps1'
$logDir = 'C:\Logs\Keyence'
$installLog = Join-Path $logDir 'install.log'
$transcriptLog = Join-Path $logDir '09-Setup-Keyence.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-KeyenceLog {
param([string]$Message, [string]$Level = 'INFO')
$stamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
Write-Host "[$stamp] [$Level] $Message"
}
Write-KeyenceLog "================================================================"
Write-KeyenceLog "=== Keyence Setup (imaging-time) session start (PID $PID) ==="
Write-KeyenceLog "Running as: $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name)"
Write-KeyenceLog "Script root: $PSScriptRoot"
Write-KeyenceLog "================================================================"
# Diagnostic dump
foreach ($file in @('pc-type.txt','pc-subtype.txt','machine-number.txt')) {
$path = "C:\Enrollment\$file"
if (Test-Path -LiteralPath $path) {
$content = (Get-Content -LiteralPath $path -First 1 -ErrorAction SilentlyContinue).Trim()
Write-KeyenceLog " $file = $content"
} else {
Write-KeyenceLog " $file = (not present)"
}
}
# ============================================================================
# Step 1: Install via manifest (imaging-time)
# ============================================================================
if (-not (Test-Path $manifestPath)) {
Write-KeyenceLog "keyence-manifest.json not found at $manifestPath" "ERROR"
} elseif (-not (Test-Path $libSource)) {
Write-KeyenceLog "Install-FromManifest.ps1 not found at $libSource" "ERROR"
} else {
Write-KeyenceLog "Running Install-FromManifest (InstallerRoot=$PSScriptRoot)"
& $libSource -ManifestPath $manifestPath -InstallerRoot $PSScriptRoot -LogFile $installLog
$rc = $LASTEXITCODE
Write-KeyenceLog "Install-FromManifest returned $rc"
}
Write-KeyenceLog "================================================================"
Write-KeyenceLog "=== Keyence Setup session end ==="
Write-KeyenceLog "================================================================"
try { Stop-Transcript | Out-Null } catch {}

View File

@@ -0,0 +1,94 @@
[Version]
Signature = "$Windows NT$"
DriverPackageDisplayName=%DESC%
Class = KeyenceUSB
ClassGuid={EE304F37-F588-45FC-91FE-B76873981AD1}
Provider = %ProviderName%
CatalogFile=KEYENCE_VR_SERIES.cat
DriverVer=03/26/2020,1.0.0.0
; ================== Class section ==================
[ClassInstall32]
Addreg=KeyenceClassReg
[KeyenceClassReg]
HKR,,,0,%ClassName%
HKR,,Icon,,-5
; ========== Manufacturer/Models sections ===========
[Manufacturer]
%ProviderName% = KEYENCE,NTamd64
[KEYENCE.NTamd64]
%USB\KeyenceDevice.DeviceDesc% =USB_Install,USB\VID_0720&PID_102C
; =================== Installation ===================
;[1]
[USB_Install]
Include=winusb.inf
Needs=WINUSB.NT
;[2]
[USB_Install.Services]
Include=winusb.inf
AddService=WinUSB,0x00000002,WinUSB_ServiceInstall
;[3]
[WinUSB_ServiceInstall]
DisplayName = %WinUSB_SvcDesc%
ServiceType = 1
StartType = 3
ErrorControl = 1
ServiceBinary = %12%\WinUSB.sys
;[4]
[USB_Install.Wdf]
KmdfService=WINUSB, WinUsb_Install
[WinUSB_Install]
KmdfLibraryVersion=1.9
;[5]
[USB_Install.HW]
AddReg=Dev_AddReg
[Dev_AddReg]
HKR,,DeviceInterfaceGUIDs,0x10000,"{B708995F-18C9-4D52-8D29-41FF2BFBF215}"
;[6]
[USB_Install.CoInstallers]
AddReg=CoInstallers_AddReg
CopyFiles=CoInstallers_CopyFiles
[CoInstallers_AddReg]
HKR,,CoInstallers32,0x00010000,"WdfCoInstaller01009.dll,WdfCoInstaller","WinUsbCoinstaller2.dll"
[CoInstallers_CopyFiles]
WdfCoInstaller01009.dll
WinUsbCoinstaller2.dll
[DestinationDirs]
CoInstallers_CopyFiles=11
; ================= Source Media Section =====================
;[7]
[SourceDisksNames]
1 = %DISK_NAME%,,,\amd64
[SourceDisksFiles.amd64]
WinUSBCoInstaller2.dll=1
WdfCoInstaller01009.dll=1
; =================== Strings ===================
[Strings]
ProviderName="KEYENCE"
DESC="VR Series USB-Driver"
WinUSB_SvcDesc="WinUSB.sys : KEYENCE USB Device"
DISK_NAME="KEYENCE USB Driver Installation Disk"
ClassName="KEYENCE USB Device Class"
USB\KeyenceDevice.DeviceDesc="VR Series"

View File

@@ -0,0 +1,25 @@
{
"Version": "1.0",
"_comment": "Keyence machine-app manifest, imaging-time only. Consumed by 09-Setup-Keyence.ps1, reading from the in-repo shopfloor-setup/Keyence/ dir xcopied by startnet.cmd. Ongoing enforcement is handled separately by GE-Enforce reading keyence/manifest.json from the tsgwp00525 share. Each entry has an InstallerRoot-relative 'Installer' path plus standard detection. The 'Type' field is MSI, EXE, or INF: INF invokes pnputil /add-driver /install. When releasing a new VR-6000 version, update the Installer path + DetectionValue here AND on the share manifest.",
"Applications": [
{
"_comment": "VR-6000 Series Software - main Keyence microscope/profilometer control app. Extracted from Keyence6000.exe (Inno Setup wrapper around an InstallShield 2019 MSI). Silent install works fine with /qn + REBOOT=ReallySuppress as long as you bypass the Inno wrapper - the wrapper's [Run] entry calls the bundled InstallShield Setup.exe without silent flags which hangs in session 0.",
"Name": "VR-6000 Series Software",
"Installer": "installers\\VR-6000 Series Software.msi",
"Type": "MSI",
"InstallArgs": "/qn /norestart ALLUSERS=1 REBOOT=ReallySuppress",
"DetectionMethod": "Registry",
"DetectionPath": "HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{058E7194-BDF8-4FA2-9D69-978BB0F25214}",
"DetectionName": "DisplayVersion",
"DetectionValue": "4.3.7"
},
{
"_comment": "KEYENCE VR Series USB driver (WinUSB-based). Pulled from DriverStore after a full interactive install because dpinst.exe in the Inno wrapper needs GUI confirmation. pnputil /add-driver /install stages the INF + cat + co-installer DLLs to the Windows DriverStore; if a physical VR device is plugged in, Windows binds it immediately. Detection checks 'pnputil /enum-drivers' output for the INF filename - this matches regardless of driver version so updates (new INF with same basename) won't false-skip.",
"Name": "KEYENCE VR Series USB Driver",
"Installer": "drivers\\keyence_vr_series.inf",
"Type": "INF",
"DetectionMethod": "pnputil",
"DetectionPattern": "keyence_vr_series\\.inf"
}
]
}