CMM first-run-as-admin, controller credential user-context fix, IE compat hash
09-Setup-CMM: add Step 2.6 that launches each installed PC-DMIS version once as admin before the PPKG locks the machine down. Also adds PC-DMIS 2026.1 to the ACL directory list. Controller credential: cmdkey /add under SYSTEM stored creds in the wrong vault. Switch to a Register script (MarkerFile detection, runs once) that creates an AtLogOn scheduled task under BUILTIN\Users so cmdkey runs in the ShopFloor user's session. IE compat: update test matrix hash for the new site list that adds wjfms3.apps.wlm.geaerospace.net. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
{ "name": "Adobe Acrobat Reader DC", "verify": { "method": "Registry", "path": "HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{AC76BA86-7AD7-1033-7B44-AC0F074E4100}", "name": "DisplayVersion", "value": "25.001.20531" } },
|
||||
{ "name": "WJF Defect Tracker", "verify": { "method": "Registry", "path": "HKLM:\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\{CC1B4D32-1606-4A3F-8F24-31312F723D5C}", "name": "DisplayVersion", "value": "01.00.0102" } },
|
||||
{ "name": "3OF9 barcode font", "verify": { "method": "File", "path": "C:\\Windows\\Fonts\\3OF9.ttf" } },
|
||||
{ "name": "Edge IE-Mode site list", "verify": { "method": "Hash", "path": "C:\\ProgramData\\Edge\\enterprise-mode-site-list.xml", "value": "16F2A6E45EFA19ED7B1C54B264D6B33597678D3A5303255BC7CEB7E8510C60FC" } }
|
||||
{ "name": "Edge IE-Mode site list", "verify": { "method": "Hash", "path": "C:\\ProgramData\\Edge\\enterprise-mode-site-list.xml", "value": "E13073B2D89E120560AF638F08519E94CC1DC880FFEF5D6A4C7011430E21E4EA" } }
|
||||
],
|
||||
"fmsResolver": [
|
||||
{ "name": "FMS hosts pin", "verify": { "method": "FileGrep", "path": "C:\\Windows\\System32\\drivers\\etc\\hosts", "pattern": "10\\.233\\.112\\.158\\s+wjfms3\\.ae\\.ge\\.com" } }
|
||||
|
||||
@@ -139,12 +139,12 @@ else {
|
||||
# PC-DMIS writes settings, probe configs, and measurement data to its own
|
||||
# install directory at runtime. Without Modify permission for BUILTIN\Users,
|
||||
# non-admin accounts get a UAC elevation prompt on every launch. Granting
|
||||
# the ACL here is the Hexagon-documented approach for non-admin deployment
|
||||
# and avoids the need for a first-run-as-admin (which hits a license dialog
|
||||
# and can't be automated silently).
|
||||
# the ACL here is the Hexagon-documented approach for non-admin deployment.
|
||||
# Step 2.6 below handles the required first-run-as-admin initialization.
|
||||
$pcdmisDirs = @(
|
||||
'C:\Program Files\Hexagon\PC-DMIS 2016.0 64-bit',
|
||||
'C:\Program Files\Hexagon\PC-DMIS 2019 R2 64-bit',
|
||||
'C:\Program Files\Hexagon\PC-DMIS 2026.1 64-bit',
|
||||
'C:\ProgramData\Hexagon',
|
||||
'C:\Program Files (x86)\General Electric\goCMM',
|
||||
'C:\Program Files\DODA'
|
||||
@@ -171,6 +171,39 @@ foreach ($dir in $pcdmisDirs) {
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Step 2.6: First-run-as-admin for each installed PC-DMIS version
|
||||
# ============================================================================
|
||||
# PC-DMIS performs one-time initialization on first launch (COM registration,
|
||||
# config file creation, internal setup). This must happen with admin rights
|
||||
# before the PPKG locks the machine down. Launch each installed version,
|
||||
# wait for it to initialize, then kill it.
|
||||
$pcdmisExes = @(
|
||||
'C:\Program Files\Hexagon\PC-DMIS 2016.0 64-bit\PCDLRN.exe',
|
||||
'C:\Program Files\Hexagon\PC-DMIS 2019 R2 64-bit\PCDLRN.exe',
|
||||
'C:\Program Files\Hexagon\PC-DMIS 2026.1 64-bit\PCDLRN.exe'
|
||||
)
|
||||
foreach ($exe in $pcdmisExes) {
|
||||
if (-not (Test-Path -LiteralPath $exe)) { continue }
|
||||
$ver = Split-Path (Split-Path $exe -Parent) -Leaf
|
||||
Write-CMMLog "First-run init: launching $ver"
|
||||
try {
|
||||
$proc = Start-Process -FilePath $exe -PassThru -ErrorAction Stop
|
||||
$initTimeout = 45
|
||||
Write-CMMLog " PID $($proc.Id) started, waiting ${initTimeout}s for initialization..."
|
||||
Start-Sleep -Seconds $initTimeout
|
||||
if (-not $proc.HasExited) {
|
||||
$proc.Kill()
|
||||
$proc.WaitForExit(10000)
|
||||
Write-CMMLog " Killed after ${initTimeout}s (first-run init complete)"
|
||||
} else {
|
||||
Write-CMMLog " Exited on its own (exit $($proc.ExitCode))"
|
||||
}
|
||||
} catch {
|
||||
Write-CMMLog " First-run launch failed: $_" 'WARN'
|
||||
}
|
||||
}
|
||||
|
||||
# ============================================================================
|
||||
# Step 3: Conditional cleanup of the bootstrap staging dir
|
||||
# ============================================================================
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
# Register-ControllerCredentialTask.ps1 - Register a user-context AtLogOn
|
||||
# scheduled task that runs Set-ControllerCredential.ps1 as the logged-in
|
||||
# user (ShopFloor). Credential Manager entries are per-user, so cmdkey /add
|
||||
# must run in the user's session, not SYSTEM.
|
||||
#
|
||||
# GE-Enforce (SYSTEM) runs THIS script via the manifest. It registers the
|
||||
# task once (MarkerFile detection prevents re-registration on subsequent
|
||||
# enforce cycles). The task itself fires at every logon and re-applies the
|
||||
# credential, covering Defender / Intune scrubs between sessions.
|
||||
#
|
||||
# Idempotent: safe to re-run. Existing task is overwritten via -Force.
|
||||
|
||||
$ErrorActionPreference = 'Continue'
|
||||
|
||||
$logDir = 'C:\Logs\Shopfloor'
|
||||
if (-not (Test-Path $logDir)) {
|
||||
try { New-Item -Path $logDir -ItemType Directory -Force | Out-Null } catch { $logDir = $env:TEMP }
|
||||
}
|
||||
$logFile = Join-Path $logDir 'register-controller-cred.log'
|
||||
|
||||
function Write-RegLog {
|
||||
param([string]$Message, [string]$Level = 'INFO')
|
||||
$line = '[{0}] [{1}] {2}' -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'), $Level, $Message
|
||||
Add-Content -Path $logFile -Value $line -ErrorAction SilentlyContinue
|
||||
Write-Host $line
|
||||
}
|
||||
|
||||
Write-RegLog '=== Register-ControllerCredentialTask start ==='
|
||||
|
||||
$taskName = 'Apply Controller Credential'
|
||||
|
||||
# The actual cmdkey script lives alongside this registration script on the
|
||||
# SFLD share. GE-Enforce mounts the share as W:, so the script path is
|
||||
# relative to the share root. At task-fire time, however, the share may not
|
||||
# be mounted. Copy the script to a local path so the logon task always works.
|
||||
$localDir = 'C:\Program Files\GE\Shopfloor\controller-cred'
|
||||
$localScript = Join-Path $localDir 'Set-ControllerCredential.ps1'
|
||||
|
||||
# Resolve the source script. When GE-Enforce runs this, $PSScriptRoot
|
||||
# points to the share-mounted dir (W:\gea-shopfloor-collections\apps\ or
|
||||
# similar). Fall back to the same directory as this script.
|
||||
$sourceScript = Join-Path $PSScriptRoot 'Set-ControllerCredential.ps1'
|
||||
if (-not (Test-Path -LiteralPath $sourceScript)) {
|
||||
Write-RegLog "Set-ControllerCredential.ps1 not found at $sourceScript" 'ERROR'
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Stage the script locally.
|
||||
if (-not (Test-Path $localDir)) {
|
||||
New-Item -Path $localDir -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
try {
|
||||
Copy-Item -LiteralPath $sourceScript -Destination $localScript -Force -ErrorAction Stop
|
||||
Write-RegLog "Staged $sourceScript -> $localScript"
|
||||
} catch {
|
||||
Write-RegLog "Failed to copy script locally: $_" 'ERROR'
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Register the logon task for BUILTIN\Users (catches ShopFloor + any
|
||||
# interactive user). RunLevel Limited -- no elevation needed for cmdkey.
|
||||
try {
|
||||
$action = New-ScheduledTaskAction `
|
||||
-Execute 'powershell.exe' `
|
||||
-Argument "-NoProfile -ExecutionPolicy Bypass -WindowStyle Hidden -File `"$localScript`""
|
||||
$trigger = New-ScheduledTaskTrigger -AtLogOn
|
||||
$principal = New-ScheduledTaskPrincipal -GroupId 'S-1-5-32-545' -RunLevel Limited
|
||||
$settings = New-ScheduledTaskSettingsSet `
|
||||
-AllowStartIfOnBatteries `
|
||||
-DontStopIfGoingOnBatteries `
|
||||
-StartWhenAvailable `
|
||||
-ExecutionTimeLimit (New-TimeSpan -Minutes 2)
|
||||
Register-ScheduledTask `
|
||||
-TaskName $taskName `
|
||||
-Action $action `
|
||||
-Trigger $trigger `
|
||||
-Principal $principal `
|
||||
-Settings $settings `
|
||||
-Force `
|
||||
-ErrorAction Stop | Out-Null
|
||||
Write-RegLog "Registered scheduled task '$taskName' (AtLogOn, BUILTIN\Users, Limited)"
|
||||
} catch {
|
||||
Write-RegLog "FAILED to register '$taskName': $_" 'ERROR'
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Write marker file so the manifest's MarkerFile detection prevents
|
||||
# re-running this registration on every enforce cycle.
|
||||
$markerDir = 'C:\ProgramData\GE\Shopfloor\markers'
|
||||
if (-not (Test-Path $markerDir)) {
|
||||
New-Item -Path $markerDir -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
$markerFile = Join-Path $markerDir 'controller-credential-task.marker'
|
||||
Set-Content -Path $markerFile -Value (Get-Date -Format 'yyyy-MM-dd HH:mm:ss') -Force
|
||||
Write-RegLog "Marker written: $markerFile"
|
||||
|
||||
Write-RegLog '=== Register-ControllerCredentialTask end ==='
|
||||
exit 0
|
||||
@@ -1,8 +1,10 @@
|
||||
{
|
||||
"_comment": "Drop this entry into the SFLD share at \\tsgwp00525\\sfld$\\v2\\shared\\dt\\shopfloor\\gea-shopfloor-collections\\manifest.json (Applications array). Edit Set-ControllerCredential.ps1 first to fill in the real $Username + $Password before pushing the script + manifest. Detection is omitted on purpose: Install-FromManifest treats missing DetectionMethod as 'not installed' and runs the script every enforce cycle, which is exactly what we want (Defender / Intune occasionally scrubs the entry; we re-apply on each cycle). cmdkey /add is idempotent so re-running is harmless. TargetMachineNumbers is optional; remove it to apply to every collections bay, or list specific machine numbers to scope down.",
|
||||
"Name": "Controller credential for Okuma LOC650 bays (192.168.1.1)",
|
||||
"_comment": "Drop this entry into the SFLD share at \\tsgwp00525\\sfld$\\v2\\shared\\dt\\shopfloor\\gea-shopfloor-collections\\manifest.json (Applications array). Place both Register-ControllerCredentialTask.ps1 AND Set-ControllerCredential.ps1 in the apps/ dir on the share. Edit Set-ControllerCredential.ps1 to fill in the real $Username + $Password before pushing. The Register script runs once under SYSTEM (MarkerFile detection), copies Set-ControllerCredential.ps1 locally, and creates an AtLogOn scheduled task that runs cmdkey /add in the ShopFloor user's session. The task re-applies every logon, covering Defender / Intune credential scrubs.",
|
||||
"Name": "Controller credential task for Okuma LOC650 bays (192.168.1.1)",
|
||||
"PCTypes": ["gea-shopfloor-collections"],
|
||||
"TargetMachineNumbers": ["3201", "3202", "3203", "3204", "3205", "3206", "3207", "3208", "3209", "3210", "3211", "3212"],
|
||||
"Script": "apps/Set-ControllerCredential.ps1",
|
||||
"Type": "PS1"
|
||||
"Script": "apps/Register-ControllerCredentialTask.ps1",
|
||||
"Type": "PS1",
|
||||
"DetectionMethod": "MarkerFile",
|
||||
"DetectionPath": "C:\\ProgramData\\GE\\Shopfloor\\markers\\controller-credential-task.marker"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user