Enhance WinRM remote script with app tracking and IP fallback
- Fix FormTracePak app_id from 68 to 76 (68 is Media Creator Full Edition) - Add installed app tracking to remote WinRM script with embedded patterns - Add IP fallback for failed hostname connections (uses recorded 10.134.* IPs) - Add getRecordedIP API endpoint to lookup primary IP by hostname - Mark 10.134.*.* as primary IPs, other ranges as secondary/equipment IPs - Fix WinRM serialization issue by converting matched apps to JSON before return 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
473
scripts/Update-PC-Minimal.ps1
Normal file
473
scripts/Update-PC-Minimal.ps1
Normal file
@@ -0,0 +1,473 @@
|
|||||||
|
# Minimal PC data collection script
|
||||||
|
# For locked-down PCs with restricted permissions
|
||||||
|
|
||||||
|
$apiUrl = "https://tsgwp00525.rd.ds.ge.com/shopdb/api.asp"
|
||||||
|
$logFile = "$env:TEMP\shopdb-update.log"
|
||||||
|
|
||||||
|
# Start fresh log
|
||||||
|
"$(Get-Date) - Starting minimal PC update" | Out-File $logFile
|
||||||
|
|
||||||
|
$data = @{
|
||||||
|
action = 'updateCompleteAsset'
|
||||||
|
hostname = $env:COMPUTERNAME
|
||||||
|
manufacturer = 'Unknown'
|
||||||
|
model = 'Unknown'
|
||||||
|
serialNumber = 'Unknown'
|
||||||
|
pcType = 'Measuring' # Default, will be updated if PC-DMIS is found
|
||||||
|
}
|
||||||
|
|
||||||
|
"Hostname: $($data.hostname)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
|
||||||
|
# Try to get serial number
|
||||||
|
try {
|
||||||
|
$bios = Get-CimInstance -ClassName Win32_BIOS -ErrorAction Stop
|
||||||
|
$data.serialNumber = $bios.SerialNumber
|
||||||
|
"Serial: $($data.serialNumber)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
} catch {
|
||||||
|
"ERROR getting serial: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
|
||||||
|
# Try to get manufacturer/model
|
||||||
|
try {
|
||||||
|
$cs = Get-CimInstance -ClassName Win32_ComputerSystem -ErrorAction Stop
|
||||||
|
$data.manufacturer = $cs.Manufacturer
|
||||||
|
$data.model = $cs.Model
|
||||||
|
"Manufacturer: $($data.manufacturer)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
"Model: $($data.model)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
} catch {
|
||||||
|
"ERROR getting system info: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get IP address using ipconfig (no elevated permissions required)
|
||||||
|
$interfaces = @()
|
||||||
|
try {
|
||||||
|
$ipconfig = ipconfig /all
|
||||||
|
$currentIP = ""
|
||||||
|
$currentMAC = ""
|
||||||
|
|
||||||
|
foreach ($line in $ipconfig) {
|
||||||
|
if ($line -match '^\S') {
|
||||||
|
# New adapter section - save previous if valid
|
||||||
|
if ($currentIP -and $currentIP -notlike '127.*' -and $currentIP -notlike '169.254.*') {
|
||||||
|
$interfaces += @{
|
||||||
|
IPAddress = $currentIP
|
||||||
|
MACAddress = $currentMAC
|
||||||
|
}
|
||||||
|
"IP: $currentIP | MAC: $currentMAC" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
$currentIP = ""
|
||||||
|
$currentMAC = ""
|
||||||
|
}
|
||||||
|
elseif ($line -match 'IPv4 Address.*:\s*(\d+\.\d+\.\d+\.\d+)') {
|
||||||
|
$currentIP = $matches[1] -replace '\(Preferred\)',''
|
||||||
|
}
|
||||||
|
elseif ($line -match 'Physical Address.*:\s*([0-9A-F-]+)') {
|
||||||
|
$currentMAC = $matches[1] -replace '-',':'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# Don't forget the last adapter
|
||||||
|
if ($currentIP -and $currentIP -notlike '127.*' -and $currentIP -notlike '169.254.*') {
|
||||||
|
$interfaces += @{
|
||||||
|
IPAddress = $currentIP
|
||||||
|
MACAddress = $currentMAC
|
||||||
|
}
|
||||||
|
"IP: $currentIP | MAC: $currentMAC" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
"ERROR getting network info: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($interfaces.Count -gt 0) {
|
||||||
|
$data.networkInterfaces = ($interfaces | ConvertTo-Json -Compress)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Try to get OS
|
||||||
|
try {
|
||||||
|
$os = Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction Stop
|
||||||
|
$data.osVersion = $os.Caption
|
||||||
|
"OS: $($data.osVersion)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
} catch {
|
||||||
|
"ERROR getting OS: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
|
||||||
|
# Try to get logged in user
|
||||||
|
try {
|
||||||
|
$data.loggedInUser = [System.Security.Principal.WindowsIdentity]::GetCurrent().Name
|
||||||
|
"User: $($data.loggedInUser)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
} catch {
|
||||||
|
"ERROR getting user: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
|
||||||
|
# Try to get machine number (no admin required for reading HKLM)
|
||||||
|
try {
|
||||||
|
$machineNo = $null
|
||||||
|
|
||||||
|
# Primary location: GE Aircraft Engines DNC registry (64-bit and 32-bit)
|
||||||
|
$regPaths = @(
|
||||||
|
"HKLM:\SOFTWARE\GE Aircraft Engines\DNC\General",
|
||||||
|
"HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\General"
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($regPath in $regPaths) {
|
||||||
|
if (Test-Path $regPath) {
|
||||||
|
$regValue = (Get-ItemProperty -Path $regPath -Name "MachineNo" -ErrorAction SilentlyContinue).MachineNo
|
||||||
|
if ($regValue) {
|
||||||
|
$machineNo = $regValue
|
||||||
|
"Machine # from registry ($regPath): $machineNo" | Tee-Object -FilePath $logFile -Append
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Fall back to DNC.ini file
|
||||||
|
if (-not $machineNo) {
|
||||||
|
$dncIniPath = "C:\DNC\DNC.ini"
|
||||||
|
if (Test-Path $dncIniPath) {
|
||||||
|
$iniContent = Get-Content $dncIniPath -Raw -ErrorAction SilentlyContinue
|
||||||
|
if ($iniContent -match 'MachineNo\s*=\s*(.+)') {
|
||||||
|
$machineNo = $matches[1].Trim()
|
||||||
|
"Machine # from DNC.ini: $machineNo" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($machineNo) {
|
||||||
|
# Check if machine number is a generic/placeholder value
|
||||||
|
# These should not be sent to API - must be set manually
|
||||||
|
# Generic machine numbers - don't send to API but can help identify PC type
|
||||||
|
$genericMachineTypes = @{
|
||||||
|
"^WJPRT" = "Measuring" # Generic printer/measuring tool
|
||||||
|
"^WJCMM" = "CMM" # Generic CMM
|
||||||
|
"^WJMEAS" = "Measuring" # Generic measuring
|
||||||
|
"^0600$" = "Wax Trace" # Wax trace machines
|
||||||
|
"^0612$" = "Part Marker" # Part markers
|
||||||
|
"^0613$" = "Part Marker" # Part markers
|
||||||
|
"^0615" = "Part Marker" # Part markers
|
||||||
|
"^TEST" = $null # Test machines - no type hint
|
||||||
|
"^TEMP" = $null # Temporary - no type hint
|
||||||
|
"^DEFAULT"= $null # Default value - no type hint
|
||||||
|
"^0+$" = $null # All zeros - no type hint
|
||||||
|
}
|
||||||
|
|
||||||
|
$isGeneric = $false
|
||||||
|
$genericTypeHint = $null
|
||||||
|
foreach ($pattern in $genericMachineTypes.Keys) {
|
||||||
|
if ($machineNo -match $pattern) {
|
||||||
|
$isGeneric = $true
|
||||||
|
$genericTypeHint = $genericMachineTypes[$pattern]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($isGeneric) {
|
||||||
|
if ($genericTypeHint) {
|
||||||
|
"Machine # '$machineNo' is generic ($genericTypeHint) - NOT sending to API (requires manual assignment)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
# Store the type hint for later use in PC type detection
|
||||||
|
$script:genericTypeHint = $genericTypeHint
|
||||||
|
} else {
|
||||||
|
"Machine # '$machineNo' is generic/placeholder - NOT sending to API (requires manual assignment)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
# Don't set $data.machineNo - leave it out of API call
|
||||||
|
} else {
|
||||||
|
$data.machineNo = $machineNo
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"No machine number found" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
"ERROR getting machine number: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for VNC installation
|
||||||
|
try {
|
||||||
|
$hasVnc = $false
|
||||||
|
|
||||||
|
# Check registry for installed programs (both 32-bit and 64-bit)
|
||||||
|
$regPaths = @(
|
||||||
|
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
|
||||||
|
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($path in $regPaths) {
|
||||||
|
if (Test-Path $path) {
|
||||||
|
$apps = Get-ItemProperty $path -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.DisplayName -like "*VNC Server*" -or $_.DisplayName -like "*VNC Connect*" -or $_.DisplayName -like "*RealVNC*" }
|
||||||
|
if ($apps) {
|
||||||
|
$hasVnc = $true
|
||||||
|
"VNC detected: $($apps.DisplayName -join ', ')" | Tee-Object -FilePath $logFile -Append
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Also check for VNC service
|
||||||
|
if (-not $hasVnc) {
|
||||||
|
$vncService = Get-Service -Name "vncserver*" -ErrorAction SilentlyContinue
|
||||||
|
if ($vncService) {
|
||||||
|
$hasVnc = $true
|
||||||
|
"VNC service detected: $($vncService.Name)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($hasVnc) {
|
||||||
|
$data.hasVnc = "1"
|
||||||
|
} else {
|
||||||
|
$data.hasVnc = "0"
|
||||||
|
"No VNC detected" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
"ERROR checking VNC: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
$data.hasVnc = "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check for WinRM status
|
||||||
|
try {
|
||||||
|
$hasWinRM = $false
|
||||||
|
|
||||||
|
# Check if WinRM service is running
|
||||||
|
$winrmService = Get-Service -Name "WinRM" -ErrorAction SilentlyContinue
|
||||||
|
if ($winrmService -and $winrmService.Status -eq "Running") {
|
||||||
|
# Also verify WinRM is configured to accept connections
|
||||||
|
try {
|
||||||
|
$winrmConfig = winrm get winrm/config/service 2>$null
|
||||||
|
if ($winrmConfig -match "AllowRemoteAccess\s*=\s*true") {
|
||||||
|
$hasWinRM = $true
|
||||||
|
"WinRM enabled and accepting connections" | Tee-Object -FilePath $logFile -Append
|
||||||
|
} else {
|
||||||
|
"WinRM service running but remote access not enabled" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
# If we can't check config, assume it's enabled if service is running
|
||||||
|
$hasWinRM = $true
|
||||||
|
"WinRM service running (config check skipped)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"WinRM service not running" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($hasWinRM) {
|
||||||
|
$data.hasWinRM = "1"
|
||||||
|
} else {
|
||||||
|
$data.hasWinRM = "0"
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
"ERROR checking WinRM: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
$data.hasWinRM = "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Load applications.csv for app matching
|
||||||
|
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
||||||
|
$csvPath = Join-Path $scriptDir "applications.csv"
|
||||||
|
$appMappings = @()
|
||||||
|
|
||||||
|
if (Test-Path $csvPath) {
|
||||||
|
try {
|
||||||
|
$appMappings = Import-Csv $csvPath | Where-Object { $_.enabled -eq "1" -and $_.app_id }
|
||||||
|
"Loaded $($appMappings.Count) app mappings from CSV" | Tee-Object -FilePath $logFile -Append
|
||||||
|
} catch {
|
||||||
|
"ERROR loading applications.csv: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
"WARNING: applications.csv not found at $csvPath" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get installed applications from registry and match against CSV
|
||||||
|
$matchedApps = @()
|
||||||
|
$hasPcDmis = $false
|
||||||
|
$hasFormTracePak = $false
|
||||||
|
$hasKeyence = $false
|
||||||
|
$hasEAS1000 = $false
|
||||||
|
$hasGoCMM = $false
|
||||||
|
$hasDODA = $false
|
||||||
|
$hasFormStatusMonitor = $false
|
||||||
|
$hasGageCal = $false
|
||||||
|
$hasNISoftware = $false
|
||||||
|
try {
|
||||||
|
$regPaths = @(
|
||||||
|
"HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*",
|
||||||
|
"HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get all installed apps
|
||||||
|
$installedApps = @()
|
||||||
|
foreach ($path in $regPaths) {
|
||||||
|
if (Test-Path $path) {
|
||||||
|
$apps = Get-ItemProperty $path -ErrorAction SilentlyContinue |
|
||||||
|
Where-Object { $_.DisplayName -and $_.DisplayName.Trim() -ne "" }
|
||||||
|
foreach ($app in $apps) {
|
||||||
|
$installedApps += @{
|
||||||
|
DisplayName = $app.DisplayName.Trim()
|
||||||
|
Version = if ($app.DisplayVersion) { $app.DisplayVersion.Trim() } else { "" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"Found $($installedApps.Count) installed applications" | Tee-Object -FilePath $logFile -Append
|
||||||
|
|
||||||
|
# Match against CSV patterns
|
||||||
|
foreach ($mapping in $appMappings) {
|
||||||
|
$patterns = $mapping.search_patterns -split '\|'
|
||||||
|
foreach ($installedApp in $installedApps) {
|
||||||
|
$matched = $false
|
||||||
|
foreach ($pattern in $patterns) {
|
||||||
|
if ($installedApp.DisplayName -match $pattern) {
|
||||||
|
$matched = $true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($matched) {
|
||||||
|
# Avoid duplicates
|
||||||
|
if (-not ($matchedApps | Where-Object { $_.appid -eq $mapping.app_id })) {
|
||||||
|
$matchedApps += @{
|
||||||
|
appid = [int]$mapping.app_id
|
||||||
|
appname = $mapping.app_name
|
||||||
|
version = $installedApp.Version
|
||||||
|
}
|
||||||
|
"$($mapping.app_name) (ID:$($mapping.app_id)) detected: $($installedApp.DisplayName)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
|
||||||
|
# Check for PC type indicators
|
||||||
|
switch ($mapping.app_name) {
|
||||||
|
"PC-DMIS" { $hasPcDmis = $true }
|
||||||
|
"goCMM" { $hasGoCMM = $true }
|
||||||
|
"DODA" { $hasDODA = $true }
|
||||||
|
"FormTracePak" { $hasFormTracePak = $true }
|
||||||
|
"FormStatusMonitor" { $hasFormStatusMonitor = $true }
|
||||||
|
"Keyence VR Series" { $hasKeyence = $true }
|
||||||
|
"GageCal" { $hasGageCal = $true }
|
||||||
|
"NI Software" { $hasNISoftware = $true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"Matched $($matchedApps.Count) tracked applications" | Tee-Object -FilePath $logFile -Append
|
||||||
|
|
||||||
|
if ($matchedApps.Count -gt 0) {
|
||||||
|
$data.installedApps = ($matchedApps | ConvertTo-Json -Compress)
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
"ERROR getting installed apps: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
|
||||||
|
# File path fallbacks for apps that may not be in registry
|
||||||
|
# Check PC-DMIS
|
||||||
|
if (-not $hasPcDmis) {
|
||||||
|
try {
|
||||||
|
$pcDmisPaths = @(
|
||||||
|
"C:\ProgramData\Hexagon\PC-DMIS*",
|
||||||
|
"C:\Program Files\Hexagon\PC-DMIS*",
|
||||||
|
"C:\Program Files (x86)\Hexagon\PC-DMIS*",
|
||||||
|
"C:\Program Files\WAI\PC-DMIS*",
|
||||||
|
"C:\Program Files (x86)\WAI\PC-DMIS*"
|
||||||
|
)
|
||||||
|
foreach ($dmisPath in $pcDmisPaths) {
|
||||||
|
if (Test-Path $dmisPath) {
|
||||||
|
$hasPcDmis = $true
|
||||||
|
"PC-DMIS found at: $dmisPath" | Tee-Object -FilePath $logFile -Append
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
"ERROR checking PC-DMIS paths: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check UDC if not already matched
|
||||||
|
if (-not ($matchedApps | Where-Object { $_.appid -eq 2 })) {
|
||||||
|
if (Test-Path "C:\Program Files\UDC") {
|
||||||
|
$matchedApps += @{ appid = 2; appname = "UDC"; version = "" }
|
||||||
|
"UDC found at: C:\Program Files\UDC" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check eDNC if not already matched
|
||||||
|
if (-not ($matchedApps | Where-Object { $_.appid -eq 8 })) {
|
||||||
|
if (Test-Path "C:\Program Files (x86)\DNC") {
|
||||||
|
$matchedApps += @{ appid = 8; appname = "eDNC"; version = "" }
|
||||||
|
"eDNC found at: C:\Program Files (x86)\DNC" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check FormTracePak if not already matched
|
||||||
|
if (-not $hasFormTracePak) {
|
||||||
|
try {
|
||||||
|
$formTracePaths = @(
|
||||||
|
"C:\Program Files\MitutoyoApp*",
|
||||||
|
"C:\Program Files (x86)\MitutoyoApp*"
|
||||||
|
)
|
||||||
|
foreach ($ftPath in $formTracePaths) {
|
||||||
|
if (Test-Path $ftPath) {
|
||||||
|
$hasFormTracePak = $true
|
||||||
|
if (-not ($matchedApps | Where-Object { $_.appid -eq 76 })) {
|
||||||
|
$matchedApps += @{ appid = 76; appname = "FormTracePak"; version = "" }
|
||||||
|
}
|
||||||
|
"FormTracePak found at: $ftPath" | Tee-Object -FilePath $logFile -Append
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
"ERROR checking FormTracePak paths: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update installedApps data if we found more apps via file paths
|
||||||
|
if ($matchedApps.Count -gt 0) {
|
||||||
|
$data.installedApps = ($matchedApps | ConvertTo-Json -Compress)
|
||||||
|
}
|
||||||
|
|
||||||
|
# Set PC type based on application detection
|
||||||
|
# Priority: CMM > Wax Trace > Keyence > EAS1000 > Part Marker > Generic hint > default Measuring
|
||||||
|
$isCMM = ($hasPcDmis -or $hasGoCMM -or $hasDODA)
|
||||||
|
$isWaxTrace = ($hasFormTracePak -or $hasFormStatusMonitor)
|
||||||
|
$isEAS1000 = ($hasGageCal -or $hasNISoftware)
|
||||||
|
|
||||||
|
if ($isCMM) {
|
||||||
|
$data.pcType = "CMM"
|
||||||
|
$detected = @()
|
||||||
|
if ($hasPcDmis) { $detected += "PC-DMIS" }
|
||||||
|
if ($hasGoCMM) { $detected += "goCMM" }
|
||||||
|
if ($hasDODA) { $detected += "DODA" }
|
||||||
|
"PC Type set to: CMM ($($detected -join ', '))" | Tee-Object -FilePath $logFile -Append
|
||||||
|
} elseif ($isWaxTrace) {
|
||||||
|
$data.pcType = "Wax Trace"
|
||||||
|
$detected = @()
|
||||||
|
if ($hasFormTracePak) { $detected += "FormTracePak" }
|
||||||
|
if ($hasFormStatusMonitor) { $detected += "FormStatusMonitor" }
|
||||||
|
"PC Type set to: Wax Trace ($($detected -join ', '))" | Tee-Object -FilePath $logFile -Append
|
||||||
|
} elseif ($hasKeyence) {
|
||||||
|
$data.pcType = "Keyence"
|
||||||
|
"PC Type set to: Keyence (Keyence VR Series)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
} elseif ($isEAS1000) {
|
||||||
|
$data.pcType = "EAS1000"
|
||||||
|
$detected = @()
|
||||||
|
if ($hasGageCal) { $detected += "GageCal" }
|
||||||
|
if ($hasNISoftware) { $detected += "NI Software" }
|
||||||
|
"PC Type set to: EAS1000 ($($detected -join ', '))" | Tee-Object -FilePath $logFile -Append
|
||||||
|
} elseif ($script:genericTypeHint) {
|
||||||
|
# Use generic machine number hint when no software detected
|
||||||
|
$data.pcType = $script:genericTypeHint
|
||||||
|
"PC Type set to: $($script:genericTypeHint) (from generic machine # - requires manual assignment)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
} else {
|
||||||
|
"No specialized apps detected, keeping type: $($data.pcType)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
|
||||||
|
# Send to API
|
||||||
|
"Sending to API: $apiUrl" | Tee-Object -FilePath $logFile -Append
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = Invoke-RestMethod -Uri $apiUrl -Method Post -Body $data -ErrorAction Stop
|
||||||
|
"API Response: $($response | ConvertTo-Json -Compress)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
|
||||||
|
if ($response.success) {
|
||||||
|
"SUCCESS - MachineID: $($response.machineid)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
} else {
|
||||||
|
"FAILED - $($response.message)" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
"ERROR calling API: $_" | Tee-Object -FilePath $logFile -Append
|
||||||
|
}
|
||||||
|
|
||||||
|
"$(Get-Date) - Done" | Tee-Object -FilePath $logFile -Append
|
||||||
@@ -339,19 +339,30 @@ function Get-RemotePCInfo {
|
|||||||
$ip = $adapter.IPAddress[$i]
|
$ip = $adapter.IPAddress[$i]
|
||||||
# Only include IPv4 addresses
|
# Only include IPv4 addresses
|
||||||
if ($ip -match '^\d+\.\d+\.\d+\.\d+$') {
|
if ($ip -match '^\d+\.\d+\.\d+\.\d+$') {
|
||||||
|
# 10.134.*.* is always primary for shopfloor PCs
|
||||||
|
$isPrimary = ($ip -like "10.134.*")
|
||||||
|
# Secondary/equipment IPs: 192.168.*, 10.0.*, 100.* or any non-10.134 private IP
|
||||||
|
$isMachineNetwork = (
|
||||||
|
($ip -like "192.168.*") -or
|
||||||
|
($ip -like "10.0.*") -or
|
||||||
|
($ip -like "100.*") -or
|
||||||
|
(($ip -like "10.*") -and ($ip -notlike "10.134.*"))
|
||||||
|
)
|
||||||
$networkInterfaces += @{
|
$networkInterfaces += @{
|
||||||
IPAddress = $ip
|
IPAddress = $ip
|
||||||
MACAddress = $adapter.MACAddress
|
MACAddress = $adapter.MACAddress
|
||||||
SubnetMask = if ($adapter.IPSubnet) { $adapter.IPSubnet[$i] } else { "" }
|
SubnetMask = if ($adapter.IPSubnet) { $adapter.IPSubnet[$i] } else { "" }
|
||||||
DefaultGateway = if ($adapter.DefaultIPGateway) { $adapter.DefaultIPGateway[0] } else { "" }
|
DefaultGateway = if ($adapter.DefaultIPGateway) { $adapter.DefaultIPGateway[0] } else { "" }
|
||||||
InterfaceName = $adapter.Description
|
InterfaceName = $adapter.Description
|
||||||
IsMachineNetwork = ($ip -like "192.168.*" -or $ip -like "10.0.*")
|
IsPrimary = $isPrimary
|
||||||
|
IsMachineNetwork = $isMachineNetwork
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$result.NetworkInterfaces = $networkInterfaces
|
# Sort so 10.134.*.* (primary) comes first
|
||||||
|
$result.NetworkInterfaces = $networkInterfaces | Sort-Object -Property @{Expression={$_.IsPrimary}; Descending=$true}
|
||||||
|
|
||||||
# Get DNC configuration if it exists
|
# Get DNC configuration if it exists
|
||||||
$dncConfig = @{}
|
$dncConfig = @{}
|
||||||
@@ -360,23 +371,57 @@ function Get-RemotePCInfo {
|
|||||||
$iniContent = Get-Content $dncIniPath -Raw
|
$iniContent = Get-Content $dncIniPath -Raw
|
||||||
# Parse INI file for common DNC settings
|
# Parse INI file for common DNC settings
|
||||||
if ($iniContent -match 'Site\s*=\s*(.+)') { $dncConfig.Site = $matches[1].Trim() }
|
if ($iniContent -match 'Site\s*=\s*(.+)') { $dncConfig.Site = $matches[1].Trim() }
|
||||||
if ($iniContent -match 'CNC\s*=\s*(.+)') { $dncConfig.CNC = $matches[1].Trim() }
|
if ($iniContent -match 'Cnc\s*=\s*(.+)') { $dncConfig.CNC = $matches[1].Trim() }
|
||||||
if ($iniContent -match 'NCIF\s*=\s*(.+)') { $dncConfig.NCIF = $matches[1].Trim() }
|
if ($iniContent -match 'NcIF\s*=\s*(.+)') { $dncConfig.NCIF = $matches[1].Trim() }
|
||||||
if ($iniContent -match 'MachineNumber\s*=\s*(.+)') { $dncConfig.MachineNumber = $matches[1].Trim() }
|
if ($iniContent -match 'MachineNo\s*=\s*(.+)') { $dncConfig.MachineNo = $matches[1].Trim() }
|
||||||
if ($iniContent -match 'FTPHost\s*=\s*(.+)') { $dncConfig.FTPHostPrimary = $matches[1].Trim() }
|
if ($iniContent -match 'FtpHostPrimary\s*=\s*(.+)') { $dncConfig.FTPHostPrimary = $matches[1].Trim() }
|
||||||
}
|
}
|
||||||
$result.DNCConfig = $dncConfig
|
$result.DNCConfig = $dncConfig
|
||||||
|
|
||||||
# Get machine number from registry or DNC config
|
# Get machine number from registry or DNC config
|
||||||
$machineNo = $null
|
$machineNo = $null
|
||||||
# Try registry first
|
# Try registry first - GE Aircraft Engines DNC location
|
||||||
$regPath = "HKLM:\SOFTWARE\GE\ShopFloor"
|
$regPaths = @(
|
||||||
|
"HKLM:\SOFTWARE\GE Aircraft Engines\DNC\General",
|
||||||
|
"HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\General"
|
||||||
|
)
|
||||||
|
foreach ($regPath in $regPaths) {
|
||||||
if (Test-Path $regPath) {
|
if (Test-Path $regPath) {
|
||||||
$machineNo = (Get-ItemProperty -Path $regPath -Name "MachineNumber" -ErrorAction SilentlyContinue).MachineNumber
|
$machineNo = (Get-ItemProperty -Path $regPath -Name "MachineNo" -ErrorAction SilentlyContinue).MachineNo
|
||||||
|
if ($machineNo) { break }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
# Fall back to DNC config
|
# Fall back to DNC config
|
||||||
if (-not $machineNo -and $dncConfig.MachineNumber) {
|
if (-not $machineNo -and $dncConfig.MachineNo) {
|
||||||
$machineNo = $dncConfig.MachineNumber
|
$machineNo = $dncConfig.MachineNo
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if machine number is generic (don't send to API)
|
||||||
|
$genericTypeHint = $null
|
||||||
|
if ($machineNo) {
|
||||||
|
$genericMachineTypes = @{
|
||||||
|
"^WJPRT" = "Measuring" # Generic printer/measuring tool
|
||||||
|
"^WJCMM" = "CMM" # Generic CMM
|
||||||
|
"^WJMEAS" = "Measuring" # Generic measuring
|
||||||
|
"^0600$" = "Wax Trace" # Wax trace machines
|
||||||
|
"^0612$" = "Part Marker" # Part markers
|
||||||
|
"^0613$" = "Part Marker" # Part markers
|
||||||
|
"^0615" = "Part Marker" # Part markers
|
||||||
|
"^TEST" = $null # Test machines
|
||||||
|
"^TEMP" = $null # Temporary
|
||||||
|
"^DEFAULT"= $null # Default value
|
||||||
|
"^0+$" = $null # All zeros
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($pattern in $genericMachineTypes.Keys) {
|
||||||
|
if ($machineNo -match $pattern) {
|
||||||
|
$genericTypeHint = $genericMachineTypes[$pattern]
|
||||||
|
$result.IsGenericMachineNo = $true
|
||||||
|
$result.GenericTypeHint = $genericTypeHint
|
||||||
|
$machineNo = $null # Don't send generic machine numbers
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
$result.MachineNo = $machineNo
|
$result.MachineNo = $machineNo
|
||||||
|
|
||||||
@@ -413,17 +458,91 @@ function Get-RemotePCInfo {
|
|||||||
}
|
}
|
||||||
$result.HasVnc = $hasVnc
|
$result.HasVnc = $hasVnc
|
||||||
|
|
||||||
# Check for PC-DMIS installation (CMM software)
|
# ================================================================
|
||||||
$hasPcDmis = $false
|
# Detect installed applications for PC type classification
|
||||||
|
# ================================================================
|
||||||
|
|
||||||
|
# Get all installed apps once for efficiency (with version info)
|
||||||
|
$installedApps = @()
|
||||||
|
$installedAppsWithVersion = @()
|
||||||
foreach ($path in $regPaths) {
|
foreach ($path in $regPaths) {
|
||||||
if (Test-Path $path) {
|
if (Test-Path $path) {
|
||||||
$pcDmisApps = Get-ItemProperty $path -ErrorAction SilentlyContinue |
|
$apps = Get-ItemProperty $path -ErrorAction SilentlyContinue |
|
||||||
Where-Object { $_.DisplayName -like "*PC-DMIS*" -or $_.DisplayName -like "*PCDMIS*" }
|
Where-Object { $_.DisplayName -and $_.DisplayName.Trim() -ne "" }
|
||||||
if ($pcDmisApps) {
|
foreach ($app in $apps) {
|
||||||
$hasPcDmis = $true
|
$installedApps += $app.DisplayName
|
||||||
|
$installedAppsWithVersion += @{
|
||||||
|
DisplayName = $app.DisplayName.Trim()
|
||||||
|
Version = if ($app.DisplayVersion) { $app.DisplayVersion.Trim() } else { "" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# ================================================================
|
||||||
|
# Match against tracked applications (embedded from applications.csv)
|
||||||
|
# ================================================================
|
||||||
|
$trackedAppPatterns = @(
|
||||||
|
@{ app_id = 2; app_name = "UDC"; patterns = @("Universal Data Collection") }
|
||||||
|
@{ app_id = 4; app_name = "CLM"; patterns = @("PPDCS", "CLM") }
|
||||||
|
@{ app_id = 6; app_name = "PC-DMIS"; patterns = @("PC-DMIS", "PCDMIS") }
|
||||||
|
@{ app_id = 7; app_name = "Oracle"; patterns = @("OracleDatabase", "Oracle Database", "Oracle.*Database") }
|
||||||
|
@{ app_id = 8; app_name = "eDNC"; patterns = @("eDNC") }
|
||||||
|
@{ app_id = 22; app_name = "OpenText"; patterns = @("OpenText", "CSF") }
|
||||||
|
@{ app_id = 30; app_name = "Tanium"; patterns = @("^Tanium Client") }
|
||||||
|
@{ app_id = 76; app_name = "FormTracePak"; patterns = @("FormTracePak", "Formtracepak", "Form Trace", "FormTrace") }
|
||||||
|
@{ app_id = 69; app_name = "Keyence VR Series"; patterns = @("VR-3000", "VR-5000", "VR-6000", "KEYENCE VR") }
|
||||||
|
@{ app_id = 70; app_name = "Genspect"; patterns = @("Genspect") }
|
||||||
|
@{ app_id = 71; app_name = "GageCal"; patterns = @("GageCal") }
|
||||||
|
@{ app_id = 72; app_name = "NI Software"; patterns = @("^NI-", "National Instruments", "NI System", "NI Measurement", "NI LabVIEW") }
|
||||||
|
@{ app_id = 73; app_name = "goCMM"; patterns = @("goCMM") }
|
||||||
|
@{ app_id = 74; app_name = "DODA"; patterns = @("Dovetail Digital Analysis", "DODA") }
|
||||||
|
@{ app_id = 75; app_name = "FormStatusMonitor"; patterns = @("FormStatusMonitor") }
|
||||||
|
)
|
||||||
|
|
||||||
|
$matchedApps = @()
|
||||||
|
foreach ($tracked in $trackedAppPatterns) {
|
||||||
|
foreach ($installedApp in $installedAppsWithVersion) {
|
||||||
|
$matched = $false
|
||||||
|
foreach ($pattern in $tracked.patterns) {
|
||||||
|
if ($installedApp.DisplayName -match $pattern) {
|
||||||
|
$matched = $true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($matched) {
|
||||||
|
# Avoid duplicates
|
||||||
|
if (-not ($matchedApps | Where-Object { $_.appid -eq $tracked.app_id })) {
|
||||||
|
$matchedApps += @{
|
||||||
|
appid = $tracked.app_id
|
||||||
|
appname = $tracked.app_name
|
||||||
|
version = $installedApp.Version
|
||||||
|
displayname = $installedApp.DisplayName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
# Store matched apps as JSON string to survive WinRM serialization
|
||||||
|
$result.MatchedAppsCount = $matchedApps.Count
|
||||||
|
$result.MatchedAppNames = ($matchedApps | ForEach-Object { $_.appname }) -join ", "
|
||||||
|
$result.AllInstalledApps = ($installedApps | Sort-Object) -join "|"
|
||||||
|
$result.AllInstalledAppsCount = $installedApps.Count
|
||||||
|
if ($matchedApps.Count -gt 0) {
|
||||||
|
$result.MatchedAppsJson = ($matchedApps | ConvertTo-Json -Compress)
|
||||||
|
} else {
|
||||||
|
$result.MatchedAppsJson = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# CMM Detection: PC-DMIS, goCMM, DODA
|
||||||
|
$hasPcDmis = $false
|
||||||
|
$hasGoCMM = $false
|
||||||
|
$hasDODA = $false
|
||||||
|
foreach ($app in $installedApps) {
|
||||||
|
if ($app -match "PC-DMIS|PCDMIS") { $hasPcDmis = $true }
|
||||||
|
if ($app -match "^goCMM") { $hasGoCMM = $true }
|
||||||
|
if ($app -match "Dovetail Digital Analysis|DODA") { $hasDODA = $true }
|
||||||
}
|
}
|
||||||
# Also check common PC-DMIS installation paths
|
# Also check common PC-DMIS installation paths
|
||||||
if (-not $hasPcDmis) {
|
if (-not $hasPcDmis) {
|
||||||
@@ -431,7 +550,8 @@ function Get-RemotePCInfo {
|
|||||||
"C:\Program Files\Hexagon\PC-DMIS*",
|
"C:\Program Files\Hexagon\PC-DMIS*",
|
||||||
"C:\Program Files (x86)\Hexagon\PC-DMIS*",
|
"C:\Program Files (x86)\Hexagon\PC-DMIS*",
|
||||||
"C:\Program Files\WAI\PC-DMIS*",
|
"C:\Program Files\WAI\PC-DMIS*",
|
||||||
"C:\Program Files (x86)\WAI\PC-DMIS*"
|
"C:\Program Files (x86)\WAI\PC-DMIS*",
|
||||||
|
"C:\ProgramData\Hexagon\PC-DMIS*"
|
||||||
)
|
)
|
||||||
foreach ($dmisPath in $pcDmisPaths) {
|
foreach ($dmisPath in $pcDmisPaths) {
|
||||||
if (Test-Path $dmisPath) {
|
if (Test-Path $dmisPath) {
|
||||||
@@ -441,6 +561,76 @@ function Get-RemotePCInfo {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
$result.HasPcDmis = $hasPcDmis
|
$result.HasPcDmis = $hasPcDmis
|
||||||
|
$result.HasGoCMM = $hasGoCMM
|
||||||
|
$result.HasDODA = $hasDODA
|
||||||
|
$result.IsCMM = ($hasPcDmis -or $hasGoCMM -or $hasDODA)
|
||||||
|
|
||||||
|
# Wax Trace Detection: FormTracePak, FormStatusMonitor
|
||||||
|
$hasFormTracePak = $false
|
||||||
|
$hasFormStatusMonitor = $false
|
||||||
|
foreach ($app in $installedApps) {
|
||||||
|
if ($app -match "FormTracePak|Formtracepak|Form Trace|FormTrace") { $hasFormTracePak = $true }
|
||||||
|
if ($app -match "FormStatusMonitor") { $hasFormStatusMonitor = $true }
|
||||||
|
}
|
||||||
|
# Check file path fallback
|
||||||
|
if (-not $hasFormTracePak) {
|
||||||
|
$ftPaths = @("C:\Program Files\MitutoyoApp*", "C:\Program Files (x86)\MitutoyoApp*")
|
||||||
|
foreach ($ftPath in $ftPaths) {
|
||||||
|
if (Test-Path $ftPath) { $hasFormTracePak = $true; break }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result.HasFormTracePak = $hasFormTracePak
|
||||||
|
$result.HasFormStatusMonitor = $hasFormStatusMonitor
|
||||||
|
$result.IsWaxTrace = ($hasFormTracePak -or $hasFormStatusMonitor)
|
||||||
|
|
||||||
|
# Keyence Detection: VR Series, Keyence VR USB Driver
|
||||||
|
$hasKeyence = $false
|
||||||
|
foreach ($app in $installedApps) {
|
||||||
|
if ($app -match "VR-3000|VR-5000|VR-6000|KEYENCE VR") {
|
||||||
|
$hasKeyence = $true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result.HasKeyence = $hasKeyence
|
||||||
|
$result.IsKeyence = $hasKeyence
|
||||||
|
|
||||||
|
# EAS1000 Detection: GageCal, NI Software (National Instruments)
|
||||||
|
$hasGageCal = $false
|
||||||
|
$hasNISoftware = $false
|
||||||
|
foreach ($app in $installedApps) {
|
||||||
|
if ($app -match "^GageCal") { $hasGageCal = $true }
|
||||||
|
if ($app -match "^NI-|National Instruments|NI System|NI Measurement|NI LabVIEW") { $hasNISoftware = $true }
|
||||||
|
}
|
||||||
|
$result.HasGageCal = $hasGageCal
|
||||||
|
$result.HasNISoftware = $hasNISoftware
|
||||||
|
$result.IsEAS1000 = ($hasGageCal -or $hasNISoftware)
|
||||||
|
|
||||||
|
# Genspect Detection (could be Keyence or EAS1000)
|
||||||
|
$hasGenspect = $false
|
||||||
|
foreach ($app in $installedApps) {
|
||||||
|
if ($app -match "^Genspect") {
|
||||||
|
$hasGenspect = $true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result.HasGenspect = $hasGenspect
|
||||||
|
|
||||||
|
# Determine PC Type based on detected software
|
||||||
|
# Priority: CMM > Wax Trace > Keyence > EAS1000 > Generic hint > Measuring (default)
|
||||||
|
$detectedPcType = "Measuring" # Default for shopfloor PCs
|
||||||
|
if ($result.IsCMM) {
|
||||||
|
$detectedPcType = "CMM"
|
||||||
|
} elseif ($result.IsWaxTrace) {
|
||||||
|
$detectedPcType = "Wax Trace"
|
||||||
|
} elseif ($result.IsKeyence) {
|
||||||
|
$detectedPcType = "Keyence"
|
||||||
|
} elseif ($result.IsEAS1000) {
|
||||||
|
$detectedPcType = "EAS1000"
|
||||||
|
} elseif ($result.GenericTypeHint) {
|
||||||
|
# Use generic machine number hint when no software detected
|
||||||
|
$detectedPcType = $result.GenericTypeHint
|
||||||
|
}
|
||||||
|
$result.DetectedPcType = $detectedPcType
|
||||||
|
|
||||||
$result.Success = $true
|
$result.Success = $true
|
||||||
} catch {
|
} catch {
|
||||||
@@ -467,8 +657,13 @@ function Send-PCDataToApi {
|
|||||||
)
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
# Determine PC type based on machine number
|
# Determine PC type - use detected type from software analysis, fallback to machine number
|
||||||
$pcType = if ($PCData.MachineNo) { "Shopfloor" } else { "Standard" }
|
$pcType = "Measuring" # Default
|
||||||
|
if ($PCData.DetectedPcType) {
|
||||||
|
$pcType = $PCData.DetectedPcType
|
||||||
|
} elseif ($PCData.MachineNo) {
|
||||||
|
$pcType = "Shopfloor"
|
||||||
|
}
|
||||||
|
|
||||||
# Build the POST body
|
# Build the POST body
|
||||||
$postData = @{
|
$postData = @{
|
||||||
@@ -504,6 +699,11 @@ function Send-PCDataToApi {
|
|||||||
$postData.dncConfig = ($PCData.DNCConfig | ConvertTo-Json -Compress)
|
$postData.dncConfig = ($PCData.DNCConfig | ConvertTo-Json -Compress)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Add matched/tracked applications (already JSON from remote scriptblock)
|
||||||
|
if ($PCData.MatchedAppsJson -and $PCData.MatchedAppsJson -ne "") {
|
||||||
|
$postData.installedApps = $PCData.MatchedAppsJson
|
||||||
|
}
|
||||||
|
|
||||||
# Send to API
|
# Send to API
|
||||||
$response = Invoke-RestMethod -Uri $ApiUrl -Method Post -Body $postData -ErrorAction Stop
|
$response = Invoke-RestMethod -Uri $ApiUrl -Method Post -Body $postData -ErrorAction Stop
|
||||||
|
|
||||||
@@ -694,6 +894,30 @@ foreach ($result in $results) {
|
|||||||
|
|
||||||
if ($result.MachineNo) {
|
if ($result.MachineNo) {
|
||||||
Write-Log " Machine #: $($result.MachineNo)" -Level "INFO"
|
Write-Log " Machine #: $($result.MachineNo)" -Level "INFO"
|
||||||
|
} elseif ($result.IsGenericMachineNo) {
|
||||||
|
Write-Log " Machine #: (generic - requires manual assignment)" -Level "WARNING"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Show detected PC type and software
|
||||||
|
if ($result.DetectedPcType) {
|
||||||
|
$detectedSoftware = @()
|
||||||
|
if ($result.HasPcDmis) { $detectedSoftware += "PC-DMIS" }
|
||||||
|
if ($result.HasGoCMM) { $detectedSoftware += "goCMM" }
|
||||||
|
if ($result.HasDODA) { $detectedSoftware += "DODA" }
|
||||||
|
if ($result.HasFormTracePak) { $detectedSoftware += "FormTracePak" }
|
||||||
|
if ($result.HasFormStatusMonitor) { $detectedSoftware += "FormStatusMonitor" }
|
||||||
|
if ($result.HasKeyence) { $detectedSoftware += "Keyence VR" }
|
||||||
|
if ($result.HasGageCal) { $detectedSoftware += "GageCal" }
|
||||||
|
if ($result.HasNISoftware) { $detectedSoftware += "NI Software" }
|
||||||
|
if ($result.HasGenspect) { $detectedSoftware += "Genspect" }
|
||||||
|
|
||||||
|
$softwareStr = if ($detectedSoftware.Count -gt 0) { " (" + ($detectedSoftware -join ", ") + ")" } else { "" }
|
||||||
|
Write-Log " PC Type: $($result.DetectedPcType)$softwareStr" -Level "INFO"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Log tracked apps count
|
||||||
|
if ($result.MatchedAppsCount -and $result.MatchedAppsCount -gt 0) {
|
||||||
|
Write-Log " Tracked Apps: $($result.MatchedAppsCount) matched ($($result.MatchedAppNames))" -Level "INFO"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Pass the result hashtable directly to the API function
|
# Pass the result hashtable directly to the API function
|
||||||
@@ -706,6 +930,22 @@ foreach ($result in $results) {
|
|||||||
|
|
||||||
if ($apiResult.Success) {
|
if ($apiResult.Success) {
|
||||||
Write-Log " -> Updated in ShopDB (MachineID: $($apiResult.MachineId))" -Level "SUCCESS"
|
Write-Log " -> Updated in ShopDB (MachineID: $($apiResult.MachineId))" -Level "SUCCESS"
|
||||||
|
|
||||||
|
# Update WinRM status - since we successfully connected via WinRM, mark it as enabled
|
||||||
|
try {
|
||||||
|
$winrmBody = @{
|
||||||
|
action = "updateWinRMStatus"
|
||||||
|
hostname = $result.Hostname
|
||||||
|
hasWinRM = "1"
|
||||||
|
}
|
||||||
|
$winrmResponse = Invoke-RestMethod -Uri $ApiUrl -Method Post -Body $winrmBody -ErrorAction Stop
|
||||||
|
if ($winrmResponse.success) {
|
||||||
|
Write-Log " -> WinRM status updated" -Level "SUCCESS"
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Log " -> WinRM status update failed (non-critical): $_" -Level "WARNING"
|
||||||
|
}
|
||||||
|
|
||||||
$successCount++
|
$successCount++
|
||||||
$successPCs += @{
|
$successPCs += @{
|
||||||
Hostname = $result.Hostname
|
Hostname = $result.Hostname
|
||||||
@@ -731,17 +971,114 @@ foreach ($result in $results) {
|
|||||||
Write-Host ""
|
Write-Host ""
|
||||||
}
|
}
|
||||||
|
|
||||||
# Report any connection errors
|
# Collect connection errors for IP fallback retry
|
||||||
|
$connectionFailures = @()
|
||||||
foreach ($err in $remoteErrors) {
|
foreach ($err in $remoteErrors) {
|
||||||
$targetPC = if ($err.TargetObject) { $err.TargetObject } else { "Unknown" }
|
$targetPC = if ($err.TargetObject) { $err.TargetObject } else { "Unknown" }
|
||||||
Write-Log "[FAIL] ${targetPC}: $($err.Exception.Message)" -Level "ERROR"
|
Write-Log "[FAIL] ${targetPC}: $($err.Exception.Message)" -Level "ERROR"
|
||||||
$failCount++
|
$connectionFailures += @{
|
||||||
$failedPCs += @{
|
|
||||||
Hostname = $targetPC
|
Hostname = $targetPC
|
||||||
|
FQDN = $targetPC
|
||||||
Error = $err.Exception.Message
|
Error = $err.Exception.Message
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# IP Fallback: Retry failed connections using recorded IP addresses (10.134.*.*)
|
||||||
|
if ($connectionFailures.Count -gt 0) {
|
||||||
|
Write-Host ""
|
||||||
|
Write-Log "Attempting IP fallback for $($connectionFailures.Count) failed connection(s)..." -Level "INFO"
|
||||||
|
|
||||||
|
foreach ($failure in $connectionFailures) {
|
||||||
|
# Extract hostname from FQDN
|
||||||
|
$hostname = $failure.FQDN -replace "\..*$", ""
|
||||||
|
|
||||||
|
# Query API for recorded IP address
|
||||||
|
try {
|
||||||
|
$ipLookupBody = @{
|
||||||
|
action = "getRecordedIP"
|
||||||
|
hostname = $hostname
|
||||||
|
}
|
||||||
|
$ipResponse = Invoke-RestMethod -Uri $ApiUrl -Method Post -Body $ipLookupBody -ErrorAction Stop
|
||||||
|
|
||||||
|
if ($ipResponse.success -and $ipResponse.ipaddress -and $ipResponse.ipaddress -match "^10\.134\.") {
|
||||||
|
$fallbackIP = $ipResponse.ipaddress
|
||||||
|
Write-Log " Found recorded IP for ${hostname}: $fallbackIP - retrying..." -Level "INFO"
|
||||||
|
|
||||||
|
# Retry connection using IP address
|
||||||
|
$ipSessionParams = @{
|
||||||
|
ComputerName = $fallbackIP
|
||||||
|
ScriptBlock = (Get-RemotePCInfo)
|
||||||
|
SessionOption = $sessionOption
|
||||||
|
Authentication = 'Negotiate'
|
||||||
|
ErrorAction = 'Stop'
|
||||||
|
}
|
||||||
|
if ($Credential) {
|
||||||
|
$ipSessionParams.Credential = $Credential
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$ipResult = Invoke-Command @ipSessionParams
|
||||||
|
|
||||||
|
if ($ipResult.Success) {
|
||||||
|
Write-Log "[OK] $($ipResult.Hostname) (via IP: $fallbackIP)" -Level "SUCCESS"
|
||||||
|
Write-Log " Serial: $($ipResult.SerialNumber) | Model: $($ipResult.Model) | OS: $($ipResult.OSVersion)" -Level "INFO"
|
||||||
|
|
||||||
|
if ($ipResult.NetworkInterfaces -and $ipResult.NetworkInterfaces.Count -gt 0) {
|
||||||
|
$ips = ($ipResult.NetworkInterfaces | ForEach-Object { $_.IPAddress }) -join ", "
|
||||||
|
Write-Log " IPs: $ips" -Level "INFO"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ipResult.DetectedPcType) {
|
||||||
|
Write-Log " PC Type: $($ipResult.DetectedPcType)" -Level "INFO"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($ipResult.MatchedAppsCount -and $ipResult.MatchedAppsCount -gt 0) {
|
||||||
|
Write-Log " Tracked Apps: $($ipResult.MatchedAppsCount) matched ($($ipResult.MatchedAppNames))" -Level "INFO"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Send to API
|
||||||
|
Write-Log " Sending to API..." -Level "INFO"
|
||||||
|
$apiResult = Send-PCDataToApi -PCData $ipResult -ApiUrl $ApiUrl
|
||||||
|
|
||||||
|
if ($apiResult.Success) {
|
||||||
|
Write-Log " -> Updated in ShopDB (MachineID: $($apiResult.MachineId))" -Level "SUCCESS"
|
||||||
|
$successCount++
|
||||||
|
$successPCs += @{
|
||||||
|
Hostname = $ipResult.Hostname
|
||||||
|
MachineId = $apiResult.MachineId
|
||||||
|
Serial = $ipResult.SerialNumber
|
||||||
|
ViaIP = $fallbackIP
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Log " -> API Error: $($apiResult.Message)" -Level "ERROR"
|
||||||
|
$failCount++
|
||||||
|
$failedPCs += @{ Hostname = $hostname; Error = "API: $($apiResult.Message)" }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Log "[FAIL] $hostname (via IP: $fallbackIP): $($ipResult.Error)" -Level "ERROR"
|
||||||
|
$failCount++
|
||||||
|
$failedPCs += @{ Hostname = $hostname; Error = $ipResult.Error }
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Log "[FAIL] $hostname (via IP: $fallbackIP): $($_.Exception.Message)" -Level "ERROR"
|
||||||
|
$failCount++
|
||||||
|
$failedPCs += @{ Hostname = $hostname; Error = $_.Exception.Message }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
# No valid IP found, add to failed list
|
||||||
|
Write-Log " No 10.134.*.* IP recorded for $hostname - skipping fallback" -Level "WARNING"
|
||||||
|
$failCount++
|
||||||
|
$failedPCs += @{ Hostname = $hostname; Error = $failure.Error }
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
Write-Log " Failed to lookup IP for ${hostname}: $($_.Exception.Message)" -Level "WARNING"
|
||||||
|
$failCount++
|
||||||
|
$failedPCs += @{ Hostname = $hostname; Error = $failure.Error }
|
||||||
|
}
|
||||||
|
Write-Host ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Final Summary
|
# Final Summary
|
||||||
Write-Host ""
|
Write-Host ""
|
||||||
Write-Host "=" * 70 -ForegroundColor Cyan
|
Write-Host "=" * 70 -ForegroundColor Cyan
|
||||||
|
|||||||
21
scripts/applications.csv
Normal file
21
scripts/applications.csv
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
app_name,app_id,search_patterns,description,enabled
|
||||||
|
UDC,2,"Universal Data Collection","Universal Data Collection - Primary shopfloor application",1
|
||||||
|
CLM,4,"PPDCS","Legacy UDC/PPDCS application",1
|
||||||
|
PPDCS,4,"PPDCS","Legacy UDC/PPDCS application (alias)",1
|
||||||
|
Oracle,7,"OracleDatabase|Oracle Database|Oracle.*Database","Oracle Database installations",1
|
||||||
|
Tanium,30,"^Tanium Client","Tanium Client - Software Deployment and Bitlocker Keys",1
|
||||||
|
PC-DMIS,6,"PC-DMIS|PCDMIS","PC-DMIS CMM Measurement Software",1
|
||||||
|
OpenText,22,"OpenText|CSF","OpenText CSF Document Management",1
|
||||||
|
eDNC,8,"eDNC","Enhanced DNC - CNC File Transfer",1
|
||||||
|
FormTracePak,76,"FormTracePak|Formtracepak|Form Trace|FormTrace","FormTracePak Wax Trace Inspection Software",1
|
||||||
|
Keyence VR Series,69,"VR-3000|VR-5000|VR-6000|KEYENCE VR","Keyence VR Series 3D Measurement Software",1
|
||||||
|
Genspect,70,"Genspect","Genspect Inspection Software",1
|
||||||
|
GageCal,71,"GageCal","GageCal Gage Calibration Software (EAS1000)",1
|
||||||
|
NI Software,72,"NI-|National Instruments|NI System|NI Measurement|NI LabVIEW|NI Package|NI Certificates|NI Logos|NI Trace|NI mDNS|NI Auth|NI Network|NI Service","National Instruments Software Suite",1
|
||||||
|
goCMM,73,"goCMM","goCMM - CMM Companion Software",1
|
||||||
|
DODA,74,"Dovetail Digital Analysis|DODA","Dovetail Digital Analysis Software (CMM)",1
|
||||||
|
FormStatusMonitor,75,"FormStatusMonitor","FormStatusMonitor - Wax Trace Companion Software",1
|
||||||
|
Java,,"Java|JavaRuntimeEnvironment","Java Runtime Environment",0
|
||||||
|
Chrome,,"Google Chrome","Google Chrome browser",0
|
||||||
|
Office,,"Microsoft Office","Microsoft Office suite",0
|
||||||
|
VNC,,"VNC|RealVNC","VNC remote access software",0
|
||||||
|
Reference in New Issue
Block a user