# Deploy-GEEnforce.ps1 # # One-shot deploy of the GE-Enforce runtime + scheduled task to an already- # imaged shopfloor PC. Use this to promote a PC from legacy per-type # enforcers (CMM-Enforce, Keyence-Enforce, Machine-Enforce, etc.) to the # unified GE-Enforce, without re-imaging. # # Usage (on target PC, as admin): # powershell -ExecutionPolicy Bypass -File .\Deploy-GEEnforce.ps1 ` # -SourceRoot '\\\\enforcer-stage' # # The SourceRoot must contain: # GE-Enforce.ps1 # lib\Install-FromManifest.ps1 # # For imaging-time deployment, Run-ShopfloorSetup.ps1 invokes # Register-GEEnforce.ps1 directly. This script is specifically for # retrofitting live PCs. param( [Parameter(Mandatory=$true)] [string]$SourceRoot, [string]$InstallRoot = 'C:\Program Files\GE\Shopfloor', [switch]$TriggerImmediate ) $ErrorActionPreference = 'Stop' function Write-DeployLog { param([string]$m) Write-Host "[Deploy-GEEnforce] $m" } if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole('Administrators')) { throw 'Must run as Administrator.' } Write-DeployLog "SourceRoot: $SourceRoot" Write-DeployLog "InstallRoot: $InstallRoot" # ---- 1. Validate source ---- $srcEnforcer = Join-Path $SourceRoot 'GE-Enforce.ps1' $srcLib = Join-Path $SourceRoot 'lib\Install-FromManifest.ps1' foreach ($p in @($srcEnforcer, $srcLib)) { if (-not (Test-Path -LiteralPath $p)) { throw "Missing source file: $p" } } # ---- 2. Stage runtime ---- Write-DeployLog "Staging runtime to $InstallRoot" $libDst = Join-Path $InstallRoot 'lib' foreach ($d in @($InstallRoot, $libDst)) { if (-not (Test-Path $d)) { New-Item -Path $d -ItemType Directory -Force | Out-Null } } Copy-Item -LiteralPath $srcEnforcer -Destination (Join-Path $InstallRoot 'GE-Enforce.ps1') -Force Copy-Item -LiteralPath $srcLib -Destination (Join-Path $libDst 'Install-FromManifest.ps1') -Force Write-DeployLog ' Runtime files copied' # ---- 3. Register scheduled task + unregister legacy ---- $registerScript = Join-Path $SourceRoot 'Register-GEEnforce.ps1' if (-not (Test-Path -LiteralPath $registerScript)) { # Fall back to the copy that should sit next to this deploy script in the # repo. In the common rollout, Register-GEEnforce.ps1 lives beside # GE-Enforce.ps1 in $SourceRoot. $registerScript = Join-Path (Split-Path -Parent $PSCommandPath) 'Register-GEEnforce.ps1' } if (-not (Test-Path -LiteralPath $registerScript)) { throw "Cannot find Register-GEEnforce.ps1 in $SourceRoot or alongside this script." } Write-DeployLog "Invoking $registerScript" & $registerScript -EnforcerPath (Join-Path $InstallRoot 'GE-Enforce.ps1') # ---- 4. Optional: trigger one enforce cycle immediately ---- if ($TriggerImmediate) { Write-DeployLog 'Triggering GE Shopfloor Enforce now via schtasks /run' & schtasks /run /tn 'GE Shopfloor Enforce' | Out-Null Start-Sleep -Seconds 3 $log = Get-ChildItem -Path 'C:\Logs\Shopfloor' -Filter 'enforce-*.log' -ErrorAction SilentlyContinue | Sort-Object LastWriteTime -Descending | Select-Object -First 1 if ($log) { Write-DeployLog "Latest log: $($log.FullName) (watching for 30s)" $end = (Get-Date).AddSeconds(30) $lastSize = 0 while ((Get-Date) -lt $end) { $size = (Get-Item $log.FullName).Length if ($size -gt $lastSize) { Get-Content -Path $log.FullName -Tail 20 -ErrorAction SilentlyContinue | ForEach-Object { Write-Host " $_" } Write-Host ' ---' $lastSize = $size } Start-Sleep -Seconds 2 } } } Write-DeployLog 'DONE. Verify with: schtasks /query /tn "GE Shopfloor Enforce" /v /fo list'