diff --git a/playbook/startnet.cmd b/playbook/startnet.cmd index b134482..5be5e20 100644 --- a/playbook/startnet.cmd +++ b/playbook/startnet.cmd @@ -149,8 +149,8 @@ if "%CMMID%"=="" ( goto enroll_menu ) echo CMM bay: %CMMID% -REM Resolve bay config (writes version.txt + doda.txt to W:\Enrollment\cmm\ -REM after W: appears). Resolution deferred to after imaging starts - store +REM Resolve bay config (writes version.txt + doda.txt to %OSDRIVE%\Enrollment\cmm\ +REM after %OSDRIVE% appears). Resolution deferred to after imaging starts - store REM the CMMID for now and resolve in the post-imaging copy block below. goto enroll_menu @@ -195,6 +195,7 @@ REM PXE webapp writes on upload - so a new ppkg goes live with no startnet edit. REM The baked-in values below are only a fallback if ppkg.conf is missing. net use Y: \\172.16.9.1\enrollment /user:pxe-upload pxe /persistent:no >nul 2>&1 set SOURCE_PPKG= +set TARGET_PPKG= set PPKG_VER= set PPKG_EXP= if exist "Y:\ppkg.conf" ( @@ -202,6 +203,7 @@ if exist "Y:\ppkg.conf" ( if /i "%%A"=="SOURCE_PPKG" set "SOURCE_PPKG=%%B" if /i "%%A"=="PPKG_VER" set "PPKG_VER=%%B" if /i "%%A"=="PPKG_EXP" set "PPKG_EXP=%%B" + if /i "%%A"=="TARGET_PPKG" set "TARGET_PPKG=%%B" ) ) if "%SOURCE_PPKG%"=="" set SOURCE_PPKG=GCCH_Prod_SFLD_v4.16.ppkg @@ -219,7 +221,32 @@ if "%enroll%"=="6" set OFFICE= if "%enroll%"=="" goto enroll_menu set PPKG= -if not "%OFFICE%"=="" set PPKG=GCCH_Prod_SFLD_%OFFICE%_%REGION%_Exp_%PPKG_EXP%_%PPKG_VER%.ppkg +REM Target filename for the staged package. +REM +REM The SFLD-era scheme encoded an Office variant in the name +REM (GCCH_Prod_SFLD___Exp__.ppkg) because one source +REM package was renamed per Office choice. MCL packages do not work that way - +REM Office is installed by Install-Office.ps1 inside the package - and renaming +REM an MCL package into the SFLD scheme just produces a misleading filename. +REM +REM So: honour TARGET_PPKG from ppkg.conf when present, otherwise keep the +REM source filename unchanged. The SFLD construction remains only as a fallback +REM for a legacy SFLD source package. +if not "%TARGET_PPKG%"=="" ( + set PPKG=%TARGET_PPKG% +) else ( + REM find, NOT findstr: findstr.exe is not in this WinPE image (find.exe is, + REM and startnet already uses it for the PESetup wait). findstr fails with + REM "not recognized", leaves errorlevel 9009, and "if errorlevel 1" then + REM takes the NON-SFLD branch for an SFLD package - so the staged ppkg keeps + REM its source name and never gets the BPRT-tagged one. + echo %SOURCE_PPKG% | find /I "_SFLD_" >NUL + if errorlevel 1 ( + set PPKG=%SOURCE_PPKG% + ) else ( + if not "%OFFICE%"=="" set PPKG=GCCH_Prod_SFLD_%OFFICE%_%REGION%_Exp_%PPKG_EXP%_%PPKG_VER%.ppkg + ) +) REM --- 2026-05-04 rename reorg: PCTYPE is set by gea_shopfloor_submenu above REM (single string, e.g. gea-shopfloor-collections). pc-subtype.txt is no @@ -368,26 +395,75 @@ echo PESetup.exe is running. Waiting for imaging to complete... REM --- Copy enrollment package and shopfloor setup as soon as Windows partition appears --- if "%PPKG%"=="" if "%PCTYPE%"=="" goto wait_finish -echo Waiting for Windows partition at W: ... +REM --- Wait for the volume PESetup applies Windows to ----------------------- +REM PESetup hardcodes W: in nine places - every copy destination, both DISM +REM offline sessions, bcdboot and reagentc - and CREATES it during its own disk +REM preparation. See docs/PESETUP-INTERNALS.md. There is nothing to search for. +REM +REM Do NOT try to locate the volume earlier by scanning for a Windows install. +REM Proven on 579C144, 2026-08-06, PESetup 4.0.0.20: +REM 11:30:07 PESetup logs the OLD install still mounted at C: +REM 11:30:18 operator presses Next +REM 11:30:20 PESetup runs DISKPART /S X:\diskpartEFI0.txt - the wipe +REM 11:30:24 a volume scan had returned that C:, startnet assigned it W: and +REM staged into the partition PESetup was mid-way through erasing. +REM Every robocopy died, "The system cannot find the path +REM specified", and NOTHING was staged. +REM 11:30:30 PESetup creates its own W: and starts copying to it +REM The SYSTEM hive is the signal that distinguishes the applied image from the +REM one being wiped: it exists only once the WIM apply has written it. Do not +REM weaken this test to "the volume exists" or "Windows is present". +set OSDRIVE= +echo Waiting for the applied Windows volume at W: ... +set OSWAIT=0 :wait_enroll +if exist W:\Windows\System32\config\system ( + set OSDRIVE=W: + goto found_os +) +set /a OSWAIT+=1 +if %OSWAIT% GEQ 120 goto os_not_found ping -n 11 127.0.0.1 >NUL -if not exist W:\Windows\System32\config\system goto wait_enroll -echo Found Windows at W: -mkdir W:\Enrollment 2>NUL +goto wait_enroll + +:os_not_found +echo. +echo ****************************************************************** +echo ERROR: no applied Windows volume found. +echo NOTHING was staged: pc-type.txt, the enrollment package and +echo shopfloor-setup are all missing. Imaging will finish but the +echo post-install setup will NOT run. Tell the PXE admin. +echo ****************************************************************** +echo. +goto cleanup_enroll + +:found_os +echo Found Windows at %OSDRIVE% + +REM No drive-letter reassignment here. PESetup owns W: and runs its own DISKPART +REM against the same disk; a second diskpart racing it destroys the volume that +REM staging is writing to. The unattend's hardcoded W:\Drivers path is PESetup's +REM own destination (CopyDrivers unzips there), so it lines up by construction. +mkdir %OSDRIVE%\Enrollment 2>NUL REM Log all copy operations to a file that persists on the target disk. REM Tech can check C:\Enrollment\winpe-staging.log post-imaging. REM Each echo in the copy block below also appends to this file via REM the >> redirect after the screen echo. robocopy /LOG+ appends its REM own output directly. -set STAGELOG=W:\Enrollment\winpe-staging.log +set STAGELOG=%OSDRIVE%\Enrollment\winpe-staging.log echo [%DATE% %TIME%] WinPE staging started >> "%STAGELOG%" echo PCTYPE=%PCTYPE% PPKG=%PPKG% MACHINENUM=%MACHINENUM% CMMID=%CMMID% >> "%STAGELOG%" REM --- Copy site config (drives site-specific values in all setup scripts) --- if exist "Y:\config\site-config.json" ( - robocopy "Y:\config" "W:\Enrollment" "site-config.json" /R:1 /W:1 /NFL /NDL /NJH /NJS - echo Copied site-config.json. - echo [%TIME%] Copied site-config.json >> "%STAGELOG%" + robocopy "Y:\config" "%OSDRIVE%\Enrollment" "site-config.json" /R:1 /W:1 /NFL /NDL /NJH /NJS + if errorlevel 8 ( + echo WARNING: site-config.json robocopy FAILED - not staged. + echo [%TIME%] FAILED: site-config.json robocopy >> "%STAGELOG%" + ) else ( + echo Copied site-config.json. + echo [%TIME%] Copied site-config.json >> "%STAGELOG%" + ) ) else ( echo WARNING: site-config.json not found on enrollment share. echo [%TIME%] WARNING: site-config.json not found >> "%STAGELOG%" @@ -395,7 +471,7 @@ if exist "Y:\config\site-config.json" ( REM --- Copy PPKG if selected (renames from SOURCE to BPRT-tagged filename) --- if "%PPKG%"=="" goto copy_pctype -robocopy "Y:\ppkgs" "W:\Enrollment" "%SOURCE_PPKG%" /R:1 /W:1 /NFL /NDL /NJH /NJS +robocopy "Y:\ppkgs" "%OSDRIVE%\Enrollment" "%SOURCE_PPKG%" /R:1 /W:1 /NFL /NDL /NJH /NJS REM robocopy exit codes: 0-7 = success, 8+ = failure (inverse of copy's 0/1). if errorlevel 8 ( echo WARNING: Failed to copy enrollment package. @@ -403,106 +479,126 @@ if errorlevel 8 ( goto copy_pctype ) REM robocopy keeps the source name; rename to the BPRT-tagged target name. -if not "%SOURCE_PPKG%"=="%PPKG%" ren "W:\Enrollment\%SOURCE_PPKG%" "%PPKG%" +if not "%SOURCE_PPKG%"=="%PPKG%" ren "%OSDRIVE%\Enrollment\%SOURCE_PPKG%" "%PPKG%" echo [%TIME%] Copied PPKG %SOURCE_PPKG% as %PPKG% >> "%STAGELOG%" -robocopy "Y:\scripts" "W:\Enrollment" "run-enrollment.ps1" "wait-for-internet.ps1" "migrate-to-wifi.ps1" /R:1 /W:1 /NFL /NDL /NJH /NJS +robocopy "Y:\scripts" "%OSDRIVE%\Enrollment" "run-enrollment.ps1" "wait-for-internet.ps1" "migrate-to-wifi.ps1" /R:1 /W:1 /NFL /NDL /NJH /NJS echo [%TIME%] Copied enrollment scripts >> "%STAGELOG%" REM --- Create enroll.cmd at drive root as manual fallback --- -> W:\enroll.cmd ( +> %OSDRIVE%\enroll.cmd ( echo @echo off echo echo Waiting for network... echo :waitnet echo ping -n 2 8.8.8.8 ^>NUL 2^>^&1 echo if errorlevel 1 goto waitnet echo echo Network connected. Running enrollment... -echo powershell.exe -ExecutionPolicy Bypass -File "C:\run-enrollment.ps1" +echo powershell.exe -ExecutionPolicy Bypass -File "C:\Enrollment\run-enrollment.ps1" ) -echo Manual fallback created at W:\enroll.cmd +echo Manual fallback created at %OSDRIVE%\enroll.cmd :copy_pctype REM --- Copy shopfloor PC type setup scripts --- if "%PCTYPE%"=="" goto cleanup_enroll -echo %PCTYPE%> W:\Enrollment\pc-type.txt +echo %PCTYPE%> %OSDRIVE%\Enrollment\pc-type.txt REM 2026-05-04 rename reorg: pc-subtype.txt no longer written. REM display-type.txt IS still written for gea-shopfloor-display because REM Install-KioskApp.cmd reads it to pick Lobby vs Dashboard installer REM and Get-PCProfile.ps1 reads it to build the Display-{type} profile key. -if not "%DISPLAYTYPE%"=="" echo %DISPLAYTYPE%> W:\Enrollment\display-type.txt -if not "%MACHINENUM%"=="" echo %MACHINENUM%> W:\Enrollment\machine-number.txt +if not "%DISPLAYTYPE%"=="" echo %DISPLAYTYPE%> %OSDRIVE%\Enrollment\display-type.txt +if not "%MACHINENUM%"=="" echo %MACHINENUM%> %OSDRIVE%\Enrollment\machine-number.txt REM Keyence model goes to BOTH keyence-model.txt (read by 09-Setup-Keyence) AND REM pc-subtype.txt (read by GE-Enforce for per-model dispatch via existing REM PCSubType wiring: looks for gea-shopfloor-keyence-\manifest.json on share). if not "%KEYENCEMODEL%"=="" ( - echo %KEYENCEMODEL%> W:\Enrollment\keyence-model.txt - echo %KEYENCEMODEL%> W:\Enrollment\pc-subtype.txt + echo %KEYENCEMODEL%> %OSDRIVE%\Enrollment\keyence-model.txt + echo %KEYENCEMODEL%> %OSDRIVE%\Enrollment\pc-subtype.txt ) REM CMM bay ID + resolved config. CMMID comes from the bay picker (e.g. CMM4). REM Written to machine-number.txt (same field collections/waxtrace use) so REM TargetMachineNumbers on the SFLD share manifest gates per-bay entries. REM resolve-cmm-bay-config.ps1 reads the CSV and writes version.txt + doda.txt -REM to W:\Enrollment\cmm\ for 09-Setup-CMM.ps1 to consume. +REM to %OSDRIVE%\Enrollment\cmm\ for 09-Setup-CMM.ps1 to consume. if "%CMMID%"=="" goto cmm_id_done -echo %CMMID%> W:\Enrollment\machine-number.txt -mkdir W:\Enrollment\cmm 2>NUL +echo %CMMID%> %OSDRIVE%\Enrollment\machine-number.txt +mkdir %OSDRIVE%\Enrollment\cmm 2>NUL if exist "Y:\installers-post\cmm\resolve-cmm-bay-config.ps1" ( - powershell.exe -NoProfile -ExecutionPolicy Bypass -File "Y:\installers-post\cmm\resolve-cmm-bay-config.ps1" -ConfigPath "Y:\installers-post\cmm\cmm-bay-config.csv" -CmmId "%CMMID%" -OutDir "W:\Enrollment\cmm" + powershell.exe -NoProfile -ExecutionPolicy Bypass -File "Y:\installers-post\cmm\resolve-cmm-bay-config.ps1" -ConfigPath "Y:\installers-post\cmm\cmm-bay-config.csv" -CmmId "%CMMID%" -OutDir "%OSDRIVE%\Enrollment\cmm" ) REM Read doda flag to set pc-subtype.txt for GE-Enforce manifest gating. REM goto-flow avoids CMD variable scoping issues inside parens blocks. -if not exist W:\Enrollment\cmm\doda.txt goto cmm_id_done -set /p CMMDODA= W:\Enrollment\pc-subtype.txt +if not exist %OSDRIVE%\Enrollment\cmm\doda.txt goto cmm_id_done +set /p CMMDODA=<%OSDRIVE%\Enrollment\cmm\doda.txt +if /i "%CMMDODA%"=="yes" echo doda> %OSDRIVE%\Enrollment\pc-subtype.txt :cmm_id_done -robocopy "Y:\shopfloor-setup" "W:\Enrollment" "Run-ShopfloorSetup.ps1" /R:1 /W:1 /NFL /NDL /NJH /NJS +robocopy "Y:\shopfloor-setup" "%OSDRIVE%\Enrollment" "Run-ShopfloorSetup.ps1" /R:1 /W:1 /NFL /NDL /NJH /NJS REM Post-boot bulk re-fetch. WinPE staging below is best-effort (it can fail if REM the Y: mount went idle-dead during the WIM apply); Fetch-StagingPayload.ps1 REM re-pulls the shopfloor-setup tree + preinstall bundle at first logon on a REM FRESH mount. The unattend FirstLogonCommands runs it before the PowerShell 7 REM MSI + Run-ShopfloorSetup. Stage the script + its source coords here. -robocopy "Y:\shopfloor-setup" "W:\Enrollment" "Fetch-StagingPayload.ps1" /R:1 /W:1 /NFL /NDL /NJH /NJS +robocopy "Y:\shopfloor-setup" "%OSDRIVE%\Enrollment" "Fetch-StagingPayload.ps1" /R:1 /W:1 /NFL /NDL /NJH /NJS REM Stage the staging self-heal directly too, so the unattend Order 5 heal step REM runs even if Fetch-StagingPayload itself did not land. Small, reliable copy. -robocopy "Y:\shopfloor-setup" "W:\Enrollment" "Verify-And-Heal-Staging.ps1" /R:1 /W:1 /NFL /NDL /NJH /NJS -> W:\Enrollment\fetch-source.txt ( +robocopy "Y:\shopfloor-setup" "%OSDRIVE%\Enrollment" "Verify-And-Heal-Staging.ps1" /R:1 /W:1 /NFL /NDL /NJH /NJS +> %OSDRIVE%\Enrollment\fetch-source.txt ( echo \\172.16.9.1\enrollment echo pxe-upload echo pxe ) REM --- Always copy Shopfloor baseline scripts --- -mkdir W:\Enrollment\shopfloor-setup 2>NUL -robocopy "Y:\shopfloor-setup" "W:\Enrollment\shopfloor-setup" "backup_lockdown.bat" /R:1 /W:1 /NFL /NDL /NJH /NJS +mkdir %OSDRIVE%\Enrollment\shopfloor-setup 2>NUL +robocopy "Y:\shopfloor-setup" "%OSDRIVE%\Enrollment\shopfloor-setup" "backup_lockdown.bat" /R:1 /W:1 /NFL /NDL /NJH /NJS if exist "Y:\shopfloor-setup\Shopfloor" ( - mkdir W:\Enrollment\shopfloor-setup\Shopfloor 2>NUL - robocopy "Y:\shopfloor-setup\Shopfloor" "W:\Enrollment\shopfloor-setup\Shopfloor" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" - if errorlevel 8 echo WARNING: shopfloor-setup\Shopfloor robocopy exit %ERRORLEVEL% - echo Copied Shopfloor baseline setup files. - echo [%TIME%] Copied Shopfloor baseline >> "%STAGELOG%" + mkdir %OSDRIVE%\Enrollment\shopfloor-setup\Shopfloor 2>NUL + robocopy "Y:\shopfloor-setup\Shopfloor" "%OSDRIVE%\Enrollment\shopfloor-setup\Shopfloor" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" + REM Report what actually happened. These echoes used to run unconditionally + REM and printed "Copied ..." for six copies that moved zero bytes. + REM %ERRORLEVEL% is not printed: inside a parenthesised block it expands at + REM PARSE time, so it shows a stale value from before the robocopy ran. + if errorlevel 8 ( + echo WARNING: shopfloor-setup\Shopfloor robocopy FAILED - nothing copied. + echo [%TIME%] FAILED: Shopfloor baseline robocopy >> "%STAGELOG%" + ) else ( + echo Copied Shopfloor baseline setup files. + echo [%TIME%] Copied Shopfloor baseline >> "%STAGELOG%" + ) ) REM --- Always copy common/ (cross-PC-type GE-Enforce dispatcher + lib live here post-v2) --- if exist "Y:\shopfloor-setup\common" ( - mkdir W:\Enrollment\shopfloor-setup\common 2>NUL - robocopy "Y:\shopfloor-setup\common" "W:\Enrollment\shopfloor-setup\common" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" - if errorlevel 8 echo WARNING: shopfloor-setup\common robocopy exit %ERRORLEVEL% - echo Copied common setup files. - echo [%TIME%] Copied common >> "%STAGELOG%" + mkdir %OSDRIVE%\Enrollment\shopfloor-setup\common 2>NUL + robocopy "Y:\shopfloor-setup\common" "%OSDRIVE%\Enrollment\shopfloor-setup\common" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" + if errorlevel 8 ( + echo WARNING: shopfloor-setup\common robocopy FAILED - nothing copied. + echo [%TIME%] FAILED: common robocopy >> "%STAGELOG%" + ) else ( + echo Copied common setup files. + echo [%TIME%] Copied common >> "%STAGELOG%" + ) ) REM --- Copy _ntlars-backups (147 per-bay .reg files restored by gea-shopfloor-{collections,nocollections}\03-RestoreEDncConfig.ps1) --- REM Same root level as common/, referenced by 03-RestoreEDncConfig.ps1 via Join-Path $PSScriptRoot '..\_ntlars-backups'. if exist "Y:\shopfloor-setup\_ntlars-backups" ( - mkdir W:\Enrollment\shopfloor-setup\_ntlars-backups 2>NUL - robocopy "Y:\shopfloor-setup\_ntlars-backups" "W:\Enrollment\shopfloor-setup\_ntlars-backups" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" - if errorlevel 8 echo WARNING: _ntlars-backups robocopy exit %ERRORLEVEL% - echo Copied _ntlars-backups. - echo [%TIME%] Copied _ntlars-backups >> "%STAGELOG%" + mkdir %OSDRIVE%\Enrollment\shopfloor-setup\_ntlars-backups 2>NUL + robocopy "Y:\shopfloor-setup\_ntlars-backups" "%OSDRIVE%\Enrollment\shopfloor-setup\_ntlars-backups" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" + if errorlevel 8 ( + echo WARNING: _ntlars-backups robocopy FAILED - nothing copied. + echo [%TIME%] FAILED: _ntlars-backups robocopy >> "%STAGELOG%" + ) else ( + echo Copied _ntlars-backups. + echo [%TIME%] Copied _ntlars-backups >> "%STAGELOG%" + ) ) REM --- Copy type-specific scripts on top of baseline --- if exist "Y:\shopfloor-setup\%PCTYPE%" ( - mkdir "W:\Enrollment\shopfloor-setup\%PCTYPE%" 2>NUL - robocopy "Y:\shopfloor-setup\%PCTYPE%" "W:\Enrollment\shopfloor-setup\%PCTYPE%" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" - if errorlevel 8 echo WARNING: shopfloor-setup\%PCTYPE% robocopy exit %ERRORLEVEL% - echo Copied %PCTYPE% setup files. - echo [%TIME%] Copied %PCTYPE% type-specific >> "%STAGELOG%" + mkdir "%OSDRIVE%\Enrollment\shopfloor-setup\%PCTYPE%" 2>NUL + robocopy "Y:\shopfloor-setup\%PCTYPE%" "%OSDRIVE%\Enrollment\shopfloor-setup\%PCTYPE%" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" + if errorlevel 8 ( + echo WARNING: shopfloor-setup\%PCTYPE% robocopy FAILED - nothing copied. + echo [%TIME%] FAILED: %PCTYPE% type-specific robocopy >> "%STAGELOG%" + ) else ( + echo Copied %PCTYPE% setup files. + echo [%TIME%] Copied %PCTYPE% type-specific >> "%STAGELOG%" + ) ) else ( echo WARNING: No setup files found for PC type %PCTYPE%. echo [%TIME%] WARNING: No setup files for %PCTYPE% >> "%STAGELOG%" @@ -510,21 +606,27 @@ if exist "Y:\shopfloor-setup\%PCTYPE%" ( REM --- Stage preinstall bundle (apps installed locally to save Azure bandwidth) --- if exist "Y:\pre-install\preinstall.json" ( - mkdir W:\PreInstall 2>NUL - mkdir W:\PreInstall\installers 2>NUL - robocopy "Y:\pre-install" "W:\PreInstall" "preinstall.json" /R:1 /W:1 /NFL /NDL /NJH /NJS + mkdir %OSDRIVE%\PreInstall 2>NUL + mkdir %OSDRIVE%\PreInstall\installers 2>NUL + robocopy "Y:\pre-install" "%OSDRIVE%\PreInstall" "preinstall.json" /R:1 /W:1 /NFL /NDL /NJH /NJS if exist "Y:\pre-install\installers" ( - robocopy "Y:\pre-install\installers" "W:\PreInstall\installers" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" - if errorlevel 8 echo WARNING: pre-install\installers robocopy exit %ERRORLEVEL% - echo Staged preinstall bundle to W:\PreInstall. + robocopy "Y:\pre-install\installers" "%OSDRIVE%\PreInstall\installers" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" + if errorlevel 8 ( + echo WARNING: pre-install\installers robocopy FAILED - nothing staged. + ) else ( + echo Staged preinstall bundle to %OSDRIVE%\PreInstall. + ) echo [%TIME%] Staged preinstall bundle >> "%STAGELOG%" ) else ( echo WARNING: Y:\pre-install\installers not found - preinstall.json staged without installers. ) if exist "Y:\pre-install\udc-backups" ( - robocopy "Y:\pre-install\udc-backups" "W:\PreInstall\udc-backups" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" - if errorlevel 8 echo WARNING: pre-install\udc-backups robocopy exit %ERRORLEVEL% - echo Staged UDC settings backups to W:\PreInstall\udc-backups. + robocopy "Y:\pre-install\udc-backups" "%OSDRIVE%\PreInstall\udc-backups" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" + if errorlevel 8 ( + echo WARNING: pre-install\udc-backups robocopy FAILED - nothing staged. + ) else ( + echo Staged UDC settings backups to %OSDRIVE%\PreInstall\udc-backups. + ) echo [%TIME%] Staged UDC backups >> "%STAGELOG%" ) ) else ( @@ -540,24 +642,32 @@ REM bootstrap exists to get the first-install through. Post-imaging, the REM unified GE-Enforce dispatcher takes over from the share for ongoing updates. if /i not "%PCTYPE%"=="gea-shopfloor-cmm" goto skip_cmm_stage if exist "Y:\installers-post\cmm\cmm-manifest.json" ( - mkdir W:\CMM-Install 2>NUL + mkdir %OSDRIVE%\CMM-Install 2>NUL REM /XD the backups tree: it holds EVERY bay's settings backup (some 240 MB REM each). Copying all of it to every imaged CMM would waste GBs. The bulk REM copy excludes it; the selected bay's backup is staged separately below. - robocopy "Y:\installers-post\cmm" "W:\CMM-Install" /E /XD "Y:\installers-post\cmm\backups" /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" - if errorlevel 8 echo WARNING: cmm robocopy exit %ERRORLEVEL% - echo Staged CMM bootstrap to W:\CMM-Install. + robocopy "Y:\installers-post\cmm" "%OSDRIVE%\CMM-Install" /E /XD "Y:\installers-post\cmm\backups" /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" + if errorlevel 8 ( + echo WARNING: cmm robocopy FAILED - CMM bootstrap NOT staged. + ) else ( + echo Staged CMM bootstrap to %OSDRIVE%\CMM-Install. + ) echo [%TIME%] Staged CMM bootstrap >> "%STAGELOG%" ) else ( echo WARNING: Y:\cmm-installers not found - CMM PC cannot install Hexagon apps at imaging time. ) REM Stage ONLY the selected bay's settings backup. 09-Setup-CMM's Restore-CMM -REM reads W:\CMM-Install\backups\%CMMID%\ to restore PC-DMIS + goCMM settings. +REM reads %OSDRIVE%\CMM-Install\backups\%CMMID%\ to restore PC-DMIS + goCMM settings. if not defined CMMID goto skip_cmm_stage if exist "Y:\installers-post\cmm\backups\%CMMID%" ( - robocopy "Y:\installers-post\cmm\backups\%CMMID%" "W:\CMM-Install\backups\%CMMID%" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" - echo Staged %CMMID% settings backup for restore. - echo [%TIME%] Staged %CMMID% backup >> "%STAGELOG%" + robocopy "Y:\installers-post\cmm\backups\%CMMID%" "%OSDRIVE%\CMM-Install\backups\%CMMID%" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" + if errorlevel 8 ( + echo WARNING: %CMMID% backup robocopy FAILED - settings will NOT restore. + echo [%TIME%] FAILED: %CMMID% backup robocopy >> "%STAGELOG%" + ) else ( + echo Staged %CMMID% settings backup for restore. + echo [%TIME%] Staged %CMMID% backup >> "%STAGELOG%" + ) ) :skip_cmm_stage @@ -572,11 +682,14 @@ REM 09-Setup-Keyence.ps1 reads C:\Enrollment\keyence-model.txt to know which. if /i not "%PCTYPE%"=="gea-shopfloor-keyence" goto skip_keyence_stage if "%KEYENCEMODEL%"=="" goto skip_keyence_stage if exist "Y:\installers-post\keyence\%KEYENCEMODEL%\manifest.json" ( - mkdir W:\KeyenceInstall 2>NUL - mkdir W:\KeyenceInstall\%KEYENCEMODEL% 2>NUL - robocopy "Y:\installers-post\keyence\%KEYENCEMODEL%" "W:\KeyenceInstall\%KEYENCEMODEL%" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" - if errorlevel 8 echo WARNING: keyence\%KEYENCEMODEL% robocopy exit %ERRORLEVEL% - echo Staged Keyence %KEYENCEMODEL% bootstrap to W:\KeyenceInstall\%KEYENCEMODEL%\. + mkdir %OSDRIVE%\KeyenceInstall 2>NUL + mkdir %OSDRIVE%\KeyenceInstall\%KEYENCEMODEL% 2>NUL + robocopy "Y:\installers-post\keyence\%KEYENCEMODEL%" "%OSDRIVE%\KeyenceInstall\%KEYENCEMODEL%" /E /MT:16 /R:1 /W:1 /NFL /NDL /LOG+:"%STAGELOG%" + if errorlevel 8 ( + echo WARNING: keyence\%KEYENCEMODEL% robocopy FAILED - nothing staged. + ) else ( + echo Staged Keyence %KEYENCEMODEL% bootstrap to %OSDRIVE%\KeyenceInstall\%KEYENCEMODEL%\. + ) echo [%TIME%] Staged Keyence %KEYENCEMODEL% >> "%STAGELOG%" ) else ( echo WARNING: Y:\installers-post\keyence\%KEYENCEMODEL% not found - Keyence %KEYENCEMODEL% cannot install at imaging time. @@ -585,44 +698,46 @@ if exist "Y:\installers-post\keyence\%KEYENCEMODEL%\manifest.json" ( REM --- Stage WaxTrace bootstrap bundle (wax/trace gea-shopfloor-waxtrace only) --- REM Three-step process: -REM 1. robocopy installers-post\waxtrace -> W:\WaxTrace-Install (everything +REM 1. robocopy installers-post\waxtrace -> %OSDRIVE%\WaxTrace-Install (everything REM EXCEPT the formtracepak\ subdir, via /XD - that subdir carries all REM 7 vendor ISOs and we only need one of them) REM 2. resolve-bay-config.ps1: reads bay-config.csv + asset_tag, writes -REM W:\Enrollment\waxtrace\{version,model,userid}.txt for 09-Setup to read +REM %OSDRIVE%\Enrollment\waxtrace\{version,model,userid}.txt for 09-Setup to read REM 3. robocopy ONLY the bay's matching FORMTRACEPAK-V.iso from REM Y:\installers-post\waxtrace\formtracepak\ onto the target disk REM (so 09-Setup-WaxAndTrace.ps1 mounts the right version per bay) if /i not "%PCTYPE%"=="gea-shopfloor-waxtrace" goto skip_waxtrace_stage if not exist "Y:\installers-post\waxtrace\waxtrace-manifest.json" goto skip_waxtrace_missing -mkdir W:\WaxTrace-Install 2>NUL +mkdir %OSDRIVE%\WaxTrace-Install 2>NUL REM robocopy /XD excludes the formtracepak\ dir up front so we don't waste REM disk + time copying 12+ GB of vendor ISOs only to delete them. The REM matched FTPak ISO gets cherry-picked below into the same target dir. REM /NFL/NDL keep the listing manageable; output left visible (no >NUL) so REM any failure is debuggable from the install log. robocopy exit codes REM 0-7 are "OK" (per Microsoft); 8+ is real failure. -robocopy "Y:\installers-post\waxtrace" "W:\WaxTrace-Install" /E /XD formtracepak /MT:16 /R:1 /W:1 /NFL /NDL -if errorlevel 8 echo WARNING: robocopy exit %ERRORLEVEL% - some files may not have copied. -mkdir W:\WaxTrace-Install\formtracepak 2>NUL -echo Staged WaxTrace bootstrap minus formtracepak\ to W:\WaxTrace-Install. -REM Resolve bay-config: writes W:\Enrollment\waxtrace\{version,model,userid}.txt -mkdir W:\Enrollment\waxtrace 2>NUL +robocopy "Y:\installers-post\waxtrace" "%OSDRIVE%\WaxTrace-Install" /E /XD formtracepak /MT:16 /R:1 /W:1 /NFL /NDL +REM Both tests read the robocopy result, so they must sit before any command +REM that sets its own errorlevel - mkdir does, which is why it moved below. +if errorlevel 8 echo WARNING: WaxTrace bootstrap robocopy FAILED - nothing staged. +if not errorlevel 8 echo Staged WaxTrace bootstrap minus formtracepak\ to %OSDRIVE%\WaxTrace-Install. +mkdir %OSDRIVE%\WaxTrace-Install\formtracepak 2>NUL +REM Resolve bay-config: writes %OSDRIVE%\Enrollment\waxtrace\{version,model,userid}.txt +mkdir %OSDRIVE%\Enrollment\waxtrace 2>NUL if not "%MACHINENUM%"=="" ( - powershell.exe -NoProfile -ExecutionPolicy Bypass -File "Y:\installers-post\waxtrace\resolve-bay-config.ps1" -Asset "%MACHINENUM%" -OutDir "W:\Enrollment\waxtrace" + powershell.exe -NoProfile -ExecutionPolicy Bypass -File "Y:\installers-post\waxtrace\resolve-bay-config.ps1" -Asset "%MACHINENUM%" -OutDir "%OSDRIVE%\Enrollment\waxtrace" ) else ( echo WARNING: no MACHINENUM set - skipping bay-config resolve. 09-Setup-WaxAndTrace will abort cleanly with no version. ) REM Read the resolved version + robocopy ONLY that FTPak ISO (avoids dumping REM 12 GB of ISOs on the bay disk; only the matched ~2 GB ISO lands locally). set WTVER= -if exist W:\Enrollment\waxtrace\version.txt set /p WTVER=.zip +REM Per-asset backup ZIPs land at %OSDRIVE%\WaxTrace-Install\backups\.zip REM as part of the robocopy bundle above (backups\ is not in the /XD list). REM 09-Setup-WaxAndTrace.ps1 Step 3b reads C:\WaxTrace-Install\backups\ REM .zip post-vendor-MSI and runs Install-FormtracepakSettings.ps1 REM -RestoreData -RestoreConfig. Total ~17 MB on disk for the whole set, no REM cherry-pick needed. if not "%MACHINENUM%"=="" ( - if exist "W:\WaxTrace-Install\backups\%MACHINENUM%.zip" ( + if exist "%OSDRIVE%\WaxTrace-Install\backups\%MACHINENUM%.zip" ( echo Backup ZIP %MACHINENUM%.zip is in the bundle - 09-Setup Step 3b will restore. ) else ( - echo INFO: No backup ZIP for %MACHINENUM% in W:\WaxTrace-Install\backups - 09-Setup will skip the restore step. + echo INFO: No backup ZIP for %MACHINENUM% in %OSDRIVE%\WaxTrace-Install\backups - 09-Setup will skip the restore step. ) ) goto skip_waxtrace_stage @@ -650,7 +765,7 @@ echo WARNING: Y:\installers-post\waxtrace not found - WaxTrace PC cannot install :pctype_done if defined STAGELOG echo [%TIME%] WinPE staging complete >> "%STAGELOG%" -REM --- BIOS update sub-stage push (fires AFTER W: copies complete) --- +REM --- BIOS update sub-stage push (fires AFTER %OSDRIVE% copies complete) --- REM check-bios.cmd drops X:\bios-fired.flag iff it actually flashed or REM staged a firmware update. Reading the flag file is more reliable than REM scanning BIOS_STATUS for substrings (caret escaping inside quoted SET