From 8e11f0824af602f534a1d5ab2b622cc04411d60f Mon Sep 17 00:00:00 2001 From: cproudlock Date: Wed, 17 Jun 2026 08:08:00 -0400 Subject: [PATCH] CMM: gocmm-debug probes the startup NRE (part-group match), checks real exe goCMM matches the registry 'Selected Part Group' against the ApplicationSettings.xml entries with a case-sensitive compare. No match -> SelectedPartGroup null -> "Object reference not set to an instance of an object" at start. This is a different failure from the registry SecurityException the script already probes. - PROBE 3: read the reg value (32-bit view) + every FullName in the XML, Ordinal-compare, and report exact / case-only / no-match / missing-XML. Case-only and no-match name the d441abd canonicalization fix as the remedy. - Version check now looks for the real goCMM.exe, not the nonexistent GEAOperatorFriendlyInterface.exe (was a false MISSING). - .bat header documents both failure modes it now diagnoses. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../gea-shopfloor-cmm/scripts/gocmm-debug.bat | 11 +++- .../gea-shopfloor-cmm/scripts/gocmm-debug.ps1 | 62 ++++++++++++++++++- 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/playbook/shopfloor-setup/gea-shopfloor-cmm/scripts/gocmm-debug.bat b/playbook/shopfloor-setup/gea-shopfloor-cmm/scripts/gocmm-debug.bat index a00ac01..aaf42bf 100644 --- a/playbook/shopfloor-setup/gea-shopfloor-cmm/scripts/gocmm-debug.bat +++ b/playbook/shopfloor-setup/gea-shopfloor-cmm/scripts/gocmm-debug.bat @@ -4,9 +4,14 @@ REM REM *** RUN THIS AS THE OPERATOR (the locked-down shop-floor user). *** REM *** DO NOT right-click "Run as administrator" - that hides the bug. *** REM -REM Reproduces the goCMM "Requested registry access is not allowed" error and -REM dumps the goCMM registry key's ACL so we can confirm the lockdown stripped -REM the BUILTIN\Users write grant. Output lands in C:\Logs\CMM\. +REM Diagnoses two goCMM failures: +REM 1. "Requested registry access is not allowed" - dumps the goCMM key ACL +REM to confirm lockdown stripped the BUILTIN\Users write grant. +REM 2. "Object reference not set to an instance of an object" at start - +REM PROBE 3 compares the registry 'Selected Part Group' against the +REM ApplicationSettings.xml part groups (case-sensitive) and names the +REM mismatch (host form / \shared vs \SHARED) that nulls SelectedPartGroup. +REM Output lands in C:\Logs\CMM\. setlocal set "HERE=%~dp0" diff --git a/playbook/shopfloor-setup/gea-shopfloor-cmm/scripts/gocmm-debug.ps1 b/playbook/shopfloor-setup/gea-shopfloor-cmm/scripts/gocmm-debug.ps1 index ed0dd3f..e1b7419 100644 --- a/playbook/shopfloor-setup/gea-shopfloor-cmm/scripts/gocmm-debug.ps1 +++ b/playbook/shopfloor-setup/gea-shopfloor-cmm/scripts/gocmm-debug.ps1 @@ -93,14 +93,74 @@ W " exported -> $regOut" W "" W "================ goCMM version + install ================" +# The goCMM MSI installs goCMM.exe (1.1.6718.x) to this dir and points the Start +# Menu shortcut at it - goCMM.exe IS the launcher. (An earlier version of this +# script checked for GEAOperatorFriendlyInterface.exe, which this product does +# NOT install - that produced a false MISSING. Check the real exe.) foreach ($p in @( - 'C:\Program Files (x86)\General Electric\goCMM\GEAOperatorFriendlyInterface.exe', + 'C:\Program Files (x86)\General Electric\goCMM\goCMM.exe', 'C:\Program Files (x86)\General Electric\goCMM\GEA_OFI_Common.dll')) { if (Test-Path $p) { $vi = (Get-Item $p).VersionInfo; W (" {0} FileVer={1} ProductVer={2}" -f (Split-Path $p -Leaf), $vi.FileVersion, $vi.ProductVersion) } else { W " MISSING: $p" } } W "" +W "================ PROBE 3: Selected Part Group vs ApplicationSettings.xml (the startup NRE) ================" +# goCMM at start matches the registry 'Selected Part Group' against the +# entries in ApplicationSettings.xml with a CASE-SENSITIVE +# (Ordinal) compare. No match -> SelectedPartGroup is null -> a startup deref +# throws "Object reference not set to an instance of an object". This is a +# DIFFERENT failure from the registry SecurityException probed above. +# Mismatch forms seen: host (bare vs FQDN) and share segment (\shared vs \SHARED). +try { + $base32 = [Microsoft.Win32.RegistryKey]::OpenBaseKey('LocalMachine','Registry32') + $kpg = $base32.OpenSubKey($key32native, $false) + $regPg = $null; $sharedDir = 'C:\geaofi' + if ($kpg) { + $regPg = [string]$kpg.GetValue('Selected Part Group','') + $sd = [string]$kpg.GetValue('Shared Data Directory','') + if ($sd) { $sharedDir = $sd.TrimEnd('\') } + $kpg.Close() + } + W (" reg 'Selected Part Group' = [{0}]" -f $regPg) + W (" Shared Data Directory = {0}" -f $sharedDir) + + $xml = Join-Path $sharedDir 'ApplicationSettings.xml' + if (-not (Test-Path $xml)) { + W " *** ApplicationSettings.xml NOT FOUND at $xml - no part groups to match -> null SelectedPartGroup -> NRE likely. <<" + } else { + $txt = [System.IO.File]::ReadAllText($xml) + # Capture FullName in both attribute (FullName="...") and element (...) forms. + $names = New-Object System.Collections.Generic.List[string] + foreach ($m in [regex]::Matches($txt, 'FullName\s*=\s*"([^"]*)"')) { $names.Add($m.Groups[1].Value) } + foreach ($m in [regex]::Matches($txt, '([^<]*)')) { $names.Add($m.Groups[1].Value) } + $names = $names | Select-Object -Unique + W (" ApplicationSettings.xml part-group FullName entries ({0}):" -f @($names).Count) + foreach ($n in $names) { W (" [{0}]" -f $n) } + + if (-not $regPg) { + W " >> reg 'Selected Part Group' is EMPTY - goCMM has no part group pinned -> null -> NRE likely. <<" + } else { + $exact = $false; $caseOnly = $false + foreach ($n in $names) { + if ([string]::Equals($n, $regPg, [StringComparison]::Ordinal)) { $exact = $true; break } + if ([string]::Equals($n, $regPg, [StringComparison]::OrdinalIgnoreCase)) { $caseOnly = $true } + } + if ($exact) { + W " >> MATCH: reg value matches an XML FullName exactly (case-sensitive). Part group is NOT the NRE cause. <<" + } elseif ($caseOnly) { + W " >> *** CASE-ONLY MATCH *** reg value matches an XML entry only when case is ignored." + W " >> goCMM's compare is case-sensitive -> Find returns null -> SelectedPartGroup null -> NRE. <<" + W " >> FIX: re-run Install-goCMMSettings.ps1 (>= commit d441abd canonicalizes host + \SHARED case). <<" + } else { + W " >> *** NO MATCH *** reg 'Selected Part Group' is absent from ApplicationSettings.xml (any case)." + W " >> Find returns null -> SelectedPartGroup null -> NRE. Wrong per-bay override, or XML from a different bay. <<" + } + } + } +} catch { W " ERROR in part-group probe: $($_.Exception.Message)" } +W "" + W "================ UAC / registry virtualization ================" (reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v EnableLUA 2>&1 | Out-String) | W (reg query "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v EnableVirtualization 2>&1 | Out-String) | W