- lib Install-FromManifest 2.5->2.6: add _CmmVersion per-entry filter (reads C:\Enrollment\cmm\version.txt). Lifted the version gate out of 09-Setup-CMM into the shared lib so imaging and GE-Enforce apply it identically and cannot drift (root cause of PC-DMIS 2016 installing on every CMM). - Install-goCMMSettings: canonicalize the part-group share host to the FQDN in both the registry and ApplicationSettings.xml. Handles bare \\tsgwp00525\ and the legacy rd.ds.ge.com domain; idempotent. VM-tested. - Report-AssetToShopDB: resolve the machine number eDNC registry first, then fall back to C:\Enrollment\machine-number.txt (matches the lib resolution order) so a freshly imaged PC still reports its number for the PC-machine relationship. - Add Update-CMMEnforcer.ps1/.bat: update one CMM's local lib to the gated version and self-heal its PC-DMIS version. - Add Debug-ShopDBReporting.ps1/.bat: one-shot reporter triage (preconditions, client log, live test POST, verdict). - Add Verify-And-Heal-Staging.ps1/.bat: post-boot check that every imaging payload arrived and re-pull anything missing from the share, including the CMM bundle and the selected bay's backup (the payload that times out in WinPE). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
200 lines
9.3 KiB
PowerShell
200 lines
9.3 KiB
PowerShell
<#
|
|
Debug-ShopDBReporting.ps1
|
|
|
|
One-shot diagnosis of why a shopfloor PC is not updating its ShopDB entry through
|
|
api.asp (action=updateCompleteAsset). Runs the whole triage and prints a verdict:
|
|
|
|
1. Preconditions - hostname, BIOS serial (api.asp requires it), eDNC MachineNo
|
|
(the PC->machine relationship needs it).
|
|
2. Client log - the latest C:\Logs\Shopfloor\report-asset-*.log POST/RESPONSE.
|
|
3. Live test POST - calls api.asp updateCompleteAsset and parses the JSON.
|
|
4. Verdict - likely cause + fix.
|
|
|
|
NOTE: the live POST WRITES to ShopDB (it is the real reporter action - an idempotent
|
|
upsert of this PC's row, same as the scheduled reporter does). Use -NoPost to skip
|
|
it and only inspect the local log + registry.
|
|
|
|
Run as administrator on the problem PC.
|
|
|
|
Params:
|
|
-ApiUrl override the api.asp endpoint
|
|
-MachineNo override the machine number sent (default: read from eDNC registry)
|
|
-NoPost do not send the live test POST
|
|
#>
|
|
param(
|
|
[string]$ApiUrl = 'https://tsgwp00525.wjs.geaerospace.net/shopdb/api.asp',
|
|
[string]$MachineNo,
|
|
[int]$TimeoutSec = 30,
|
|
[switch]$NoPost
|
|
)
|
|
|
|
$ErrorActionPreference = 'Continue'
|
|
function Section($t){ Write-Host ''; Write-Host ("==== {0} ====" -f $t) -ForegroundColor Cyan }
|
|
function KV($k,$v){ Write-Host (" {0,-20}: {1}" -f $k, $v) }
|
|
|
|
Write-Host '########################################################'
|
|
Write-Host '# ShopDB Reporting Debug'
|
|
Write-Host ("# {0}" -f (Get-Date -Format 'yyyy-MM-dd HH:mm:ss'))
|
|
Write-Host '########################################################'
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 1. Preconditions
|
|
# ---------------------------------------------------------------------------
|
|
Section '1. Preconditions'
|
|
$hostname = $env:COMPUTERNAME
|
|
$serial = ''
|
|
try { $serial = (Get-CimInstance Win32_BIOS -ErrorAction Stop).SerialNumber } catch {
|
|
try { $serial = (Get-WmiObject Win32_BIOS -ErrorAction Stop).SerialNumber } catch {}
|
|
}
|
|
$serial = ("" + $serial).Trim()
|
|
|
|
# Resolve machine number the same way the reporter / GE-Enforce lib do:
|
|
# eDNC registry (WOW6432Node then native) first, then C:\Enrollment\machine-number.txt.
|
|
$regMachineNo = ''
|
|
foreach ($rp in @('HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\General',
|
|
'HKLM:\SOFTWARE\GE Aircraft Engines\DNC\General')) {
|
|
if ($regMachineNo) { break }
|
|
if (Test-Path $rp) {
|
|
try { $regMachineNo = ("" + (Get-ItemProperty -Path $rp -Name MachineNo -ErrorAction Stop).MachineNo).Trim() } catch {}
|
|
}
|
|
}
|
|
$txtMachineNo = ''
|
|
$mnFile = 'C:\Enrollment\machine-number.txt'
|
|
if (Test-Path -LiteralPath $mnFile) {
|
|
try { $txtMachineNo = ("" + (Get-Content -LiteralPath $mnFile -First 1 -ErrorAction Stop)).Trim() } catch {}
|
|
}
|
|
$machineNoSource = ''
|
|
if (-not $MachineNo) {
|
|
if ($regMachineNo) { $MachineNo = $regMachineNo; $machineNoSource = 'eDNC registry' }
|
|
elseif ($txtMachineNo) { $MachineNo = $txtMachineNo; $machineNoSource = 'machine-number.txt (fallback)' }
|
|
} else { $machineNoSource = 'override param' }
|
|
|
|
$corpIp = ''
|
|
try {
|
|
$corpIp = (Get-NetIPAddress -AddressFamily IPv4 -ErrorAction Stop |
|
|
Where-Object { $_.IPAddress -notmatch '^(127\.|169\.254\.)' } |
|
|
Select-Object -First 1).IPAddress
|
|
} catch {}
|
|
|
|
KV 'Hostname' $hostname
|
|
KV 'BIOS serial' ($(if ($serial) { $serial } else { '(MISSING - api.asp will reject)' }))
|
|
KV 'eDNC MachineNo (reg)' ($(if ($regMachineNo) { $regMachineNo } else { '(none)' }))
|
|
KV 'machine-number.txt' ($(if ($txtMachineNo) { $txtMachineNo } else { '(none)' }))
|
|
KV 'MachineNo to send' ($(if ($MachineNo) { "$MachineNo [from $machineNoSource]" } else { '(none - relationship will be skipped)' }))
|
|
KV 'Corp IPv4' ($(if ($corpIp) { $corpIp } else { '(none found)' }))
|
|
KV 'API endpoint' $ApiUrl
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 2. Latest client reporter log
|
|
# ---------------------------------------------------------------------------
|
|
Section '2. Latest client reporter log'
|
|
$logDir = 'C:\Logs\Shopfloor'
|
|
$log = $null
|
|
if (Test-Path $logDir) {
|
|
$log = Get-ChildItem -Path $logDir -Filter 'report-asset-*.log' -ErrorAction SilentlyContinue |
|
|
Sort-Object LastWriteTime | Select-Object -Last 1
|
|
}
|
|
if ($log) {
|
|
KV 'Log file' $log.FullName
|
|
KV 'Last written' $log.LastWriteTime
|
|
Write-Host ' --- last POST / RESPONSE / ERROR lines ---'
|
|
Get-Content $log.FullName -ErrorAction SilentlyContinue |
|
|
Select-String -Pattern 'POST |RESPONSE |ERROR ' |
|
|
Select-Object -Last 6 | ForEach-Object { Write-Host (" " + $_.Line) }
|
|
} else {
|
|
Write-Host ' No report-asset-*.log found. The reporter may never have run on this PC.'
|
|
Write-Host ' -> check the scheduled task / GE-Enforce entry that invokes Report-AssetToShopDB.ps1'
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 3. Live test POST
|
|
# ---------------------------------------------------------------------------
|
|
Section '3. Live test POST to api.asp'
|
|
$resp = $null; $postErr = $null; $rawText = $null
|
|
if ($NoPost) {
|
|
Write-Host ' -NoPost set: skipping the live POST.'
|
|
} elseif (-not $serial) {
|
|
Write-Host ' SKIPPED: no BIOS serial, api.asp requires serialNumber. Fix the hardware/WMI read first.'
|
|
} else {
|
|
# Accept the internal IIS certificate for this run (PS 5.1-safe).
|
|
try {
|
|
if (-not ([System.Management.Automation.PSTypeName]'TrustAllCerts').Type) {
|
|
Add-Type @"
|
|
using System.Net; using System.Security.Cryptography.X509Certificates;
|
|
public class TrustAllCerts : ICertificatePolicy {
|
|
public bool CheckValidationResult(ServicePoint sp, X509Certificate c, WebRequest r, int p) { return true; }
|
|
}
|
|
"@
|
|
}
|
|
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCerts
|
|
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
|
|
} catch {}
|
|
|
|
$body = @{
|
|
action = 'updateCompleteAsset'
|
|
hostname = $hostname
|
|
serialNumber = $serial
|
|
pcType = 'Shopfloor'
|
|
}
|
|
if ($MachineNo) { $body['machineNo'] = $MachineNo }
|
|
|
|
Write-Host (" POST host={0} serial={1} machineNo={2}" -f $hostname, $serial, $(if ($MachineNo) { $MachineNo } else { '(none)' }))
|
|
try {
|
|
$resp = Invoke-RestMethod -Uri $ApiUrl -Method Post -Body $body -TimeoutSec $TimeoutSec -ErrorAction Stop
|
|
Write-Host ' --- response JSON ---'
|
|
Write-Host (" " + ($resp | ConvertTo-Json -Compress -Depth 5))
|
|
} catch {
|
|
$postErr = $_.Exception.Message
|
|
Write-Host (" POST FAILED: {0}" -f $postErr) -ForegroundColor Red
|
|
try { $rawText = $_.Exception.Response } catch {}
|
|
}
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# 4. Verdict
|
|
# ---------------------------------------------------------------------------
|
|
Section '4. VERDICT'
|
|
function Truthy($v){ return ($v -eq $true -or "$v" -eq 'True' -or "$v" -eq '1') }
|
|
|
|
if ($NoPost) {
|
|
Write-Host ' (live POST skipped) Inspect section 1-2 above.'
|
|
if (-not $MachineNo) { Write-Host ' NOTE: no machine number (eDNC registry and machine-number.txt both empty) -> no relationship until set.' -ForegroundColor Yellow }
|
|
}
|
|
elseif ($postErr) {
|
|
Write-Host ' CANNOT REACH api.asp - network, TLS, DNS, or IIS error.' -ForegroundColor Red
|
|
Write-Host (" Detail: {0}" -f $postErr)
|
|
Write-Host ' -> ping/curl the host, confirm IIS is up, check the cert and the /shopdb/ path.'
|
|
}
|
|
elseif (-not $serial) {
|
|
Write-Host ' BIOS SERIAL MISSING - api.asp rejects the POST (serialNumber required).' -ForegroundColor Red
|
|
Write-Host ' -> fix WMI/Win32_BIOS on this PC; it is a hardware/OS read issue, not ShopDB.'
|
|
}
|
|
elseif (-not (Truthy $resp.success)) {
|
|
Write-Host ' SERVER RETURNED success=false - it aborted at a DB step.' -ForegroundColor Red
|
|
Write-Host (" Breadcrumb/message: {0}" -f $resp.message)
|
|
Write-Host ' -> the LAST "N-OK," token in that message is where it stopped. Match N to api.asp.'
|
|
}
|
|
elseif (-not (Truthy $resp.relationshipCreated)) {
|
|
if (-not $MachineNo) {
|
|
Write-Host ' ASSET OK, but NO RELATIONSHIP because this PC has no machine number.' -ForegroundColor Yellow
|
|
Write-Host (" machineid={0}. Neither the eDNC registry nor C:\Enrollment\machine-number.txt" -f $resp.machineid)
|
|
Write-Host ' has a value, so api.asp skips the relationship by design.'
|
|
Write-Host ' -> set the bay machine number (Set-MachineNumber writes the eDNC registry), then'
|
|
Write-Host ' re-run. CMM/keyence/wax-trace bays have no DNC number and register asset-only.'
|
|
} else {
|
|
Write-Host ' ASSET OK, but RELATIONSHIP NOT CREATED even though MachineNo was sent.' -ForegroundColor Red
|
|
Write-Host (" machineid={0}, machineNo={1}." -f $resp.machineid, $MachineNo)
|
|
Write-Host ' -> this is the server-side silent abort (LogToFile Err-leak). Deploy the api.asp fix'
|
|
Write-Host ' (commit a4051e3) to prod IIS, then re-run. Also confirm the IIS logs dir is'
|
|
Write-Host ' writable by the app-pool identity (that is the trigger).'
|
|
}
|
|
}
|
|
else {
|
|
Write-Host ' HEALTHY.' -ForegroundColor Green
|
|
Write-Host (" Asset updated (machineid={0}) and PC->machine relationship created." -f $resp.machineid)
|
|
Write-Host ' If ShopDB still looks wrong, the issue is data/display, not the reporter path.'
|
|
}
|
|
|
|
Write-Host ''
|
|
Write-Host 'Done.'
|