Files
powershell-scripts/asset-collection/Get-ShopfloorConfig.ps1
cproudlock 62c0c7bb06 Initial commit: Organized PowerShell scripts for ShopDB asset collection
Structure:
- asset-collection/: Local PC data collection scripts
- remote-execution/: WinRM remote execution scripts
- setup-utilities/: Configuration and testing utilities
- registry-backup/: GE registry backup scripts
- winrm-https/: WinRM HTTPS certificate setup
- docs/: Complete documentation

Each folder includes a README with detailed documentation.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-10 10:57:54 -05:00

480 lines
22 KiB
PowerShell

# Functions to collect shopfloor PC network and communication configurations
# Function to get all network interfaces and their configurations
function Get-NetworkInterfaceConfig {
Write-Host " Collecting network interface information..." -ForegroundColor Yellow
$interfaces = @()
try {
# Get all network adapters with IP configurations
$adapters = Get-NetAdapter | Where-Object { $_.Status -eq 'Up' }
foreach ($adapter in $adapters) {
$ipConfig = Get-NetIPConfiguration -InterfaceIndex $adapter.ifIndex -ErrorAction SilentlyContinue
if ($ipConfig -and $ipConfig.IPv4Address) {
foreach ($ip in $ipConfig.IPv4Address) {
$gateway = if ($ipConfig.IPv4DefaultGateway) { $ipConfig.IPv4DefaultGateway[0].NextHop } else { $null }
# Determine if this is a machine network (192.168.*.*)
$isMachineNetwork = $ip.IPAddress -match '^192\.168\.'
$interface = @{
InterfaceName = $adapter.Name
IPAddress = $ip.IPAddress
SubnetMask = $ip.PrefixLength # Will need conversion
DefaultGateway = $gateway
MACAddress = $adapter.MacAddress
IsDHCP = if ($ipConfig.NetIPv4Interface.Dhcp -eq 'Enabled') { 1 } else { 0 }
IsActive = 1
IsMachineNetwork = if ($isMachineNetwork) { 1 } else { 0 }
}
$interfaces += $interface
if ($isMachineNetwork) {
Write-Host " Found machine network: $($ip.IPAddress) on $($adapter.Name)" -ForegroundColor Cyan
}
else {
Write-Host " Found network: $($ip.IPAddress) on $($adapter.Name)" -ForegroundColor Gray
}
}
}
}
}
catch {
Write-Host " Error collecting network info: $_" -ForegroundColor Red
}
# Alternative method using WMI if NetAdapter cmdlets fail
if ($interfaces.Count -eq 0) {
try {
$wmiAdapters = Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object { $_.IPEnabled -eq $true }
foreach ($adapter in $wmiAdapters) {
if ($adapter.IPAddress) {
foreach ($i in 0..($adapter.IPAddress.Count - 1)) {
$ip = $adapter.IPAddress[$i]
# Skip IPv6 addresses
if ($ip -match ':') { continue }
$isMachineNetwork = $ip -match '^192\.168\.'
$interface = @{
InterfaceName = $adapter.Description
IPAddress = $ip
SubnetMask = $adapter.IPSubnet[$i]
DefaultGateway = if ($adapter.DefaultIPGateway) { $adapter.DefaultIPGateway[0] } else { $null }
MACAddress = $adapter.MACAddress
IsDHCP = $adapter.DHCPEnabled
IsActive = 1
IsMachineNetwork = if ($isMachineNetwork) { 1 } else { 0 }
}
$interfaces += $interface
if ($isMachineNetwork) {
Write-Host " Found machine network: $ip on $($adapter.Description)" -ForegroundColor Cyan
}
}
}
}
}
catch {
Write-Host " WMI method also failed: $_" -ForegroundColor Red
}
}
return $interfaces
}
# Function to get serial port configurations from registry
function Get-SerialPortConfig {
Write-Host " Collecting serial port configurations..." -ForegroundColor Yellow
$configs = @()
# Registry paths to check
$registryPaths = @{
'Serial' = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\Serial', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\Serial')
'Mark' = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\Mark', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\Mark')
'PPDCS' = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\PPDCS', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\PPDCS')
'TQM9030' = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\TQM9030', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\TQM9030')
'TQMCaron' = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\TQMCaron', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\TQMCaron')
}
foreach ($configType in $registryPaths.Keys) {
foreach ($path in $registryPaths[$configType]) {
if (Test-Path $path) {
try {
$regValues = Get-ItemProperty -Path $path -ErrorAction SilentlyContinue
if ($regValues) {
$config = @{
ConfigType = $configType
PortID = $regValues.'Port Id' -replace 'Port Id2', ''
Baud = $regValues.Baud
DataBits = $regValues.'Data Bits'
StopBits = $regValues.'Stop Bits'
Parity = $regValues.Parity
CRLF = $regValues.CRLF
IPAddress = $null
SocketNo = $null
AdditionalSettings = @{}
}
# Collect any additional settings
$standardKeys = @('Port Id', 'Baud', 'Data Bits', 'Stop Bits', 'Parity', 'CRLF', 'PSPath', 'PSParentPath', 'PSChildName', 'PSProvider')
foreach ($prop in $regValues.PSObject.Properties) {
if ($prop.Name -notin $standardKeys -and $prop.Value) {
$config.AdditionalSettings[$prop.Name] = $prop.Value
}
}
# Convert additional settings to JSON
if ($config.AdditionalSettings.Count -gt 0) {
$config.AdditionalSettings = $config.AdditionalSettings | ConvertTo-Json -Compress
}
else {
$config.AdditionalSettings = $null
}
if ($config.PortID) {
$configs += $config
Write-Host " Found $configType config: Port $($config.PortID), Baud $($config.Baud)" -ForegroundColor Cyan
}
}
}
catch {
Write-Host " Error reading $configType registry: $_" -ForegroundColor Red
}
}
}
}
# Check for eFocas configuration (network-based)
$efocasPaths = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\eFocas', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\eFocas')
foreach ($path in $efocasPaths) {
if (Test-Path $path) {
try {
$regValues = Get-ItemProperty -Path $path -ErrorAction SilentlyContinue
if ($regValues -and $regValues.IpAddr) {
$config = @{
ConfigType = 'eFocas'
PortID = $null
Baud = $null
DataBits = $null
StopBits = $null
Parity = $null
CRLF = $null
IPAddress = $regValues.IpAddr
SocketNo = $regValues.SocketNo
AdditionalSettings = @{
DualPath = $regValues.DualPath
Path1Name = $regValues.Path1Name
Path2Name = $regValues.Path2Name
Danobat = $regValues.Danobat
DataServer = $regValues.DataServer
} | ConvertTo-Json -Compress
}
$configs += $config
Write-Host " Found eFocas config: IP $($config.IPAddress), Socket $($config.SocketNo)" -ForegroundColor Cyan
}
}
catch {
Write-Host " Error reading eFocas registry: $_" -ForegroundColor Red
}
}
}
return $configs
}
# Function to get GE Aircraft Engines registry information and DualPath configuration
function Get-GERegistryInfo {
Write-Host " Collecting GE Aircraft Engines registry information..." -ForegroundColor Yellow
$geInfo = @{
Registry32Bit = $false
Registry64Bit = $false
DualPathEnabled = $null
Path1Name = $null
Path2Name = $null
RegistryNotes = @{}
}
# Check both 32-bit and 64-bit registry paths
$registryPaths = @{
'32bit' = 'HKLM:\SOFTWARE\GE Aircraft Engines'
'64bit' = 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines'
}
foreach ($pathType in $registryPaths.Keys) {
$basePath = $registryPaths[$pathType]
Write-Host " Checking $pathType registry: $basePath" -ForegroundColor Gray
if (Test-Path $basePath) {
Write-Host " [FOUND] GE Aircraft Engines in $pathType registry" -ForegroundColor Green
if ($pathType -eq '32bit') {
$geInfo.Registry32Bit = $true
} else {
$geInfo.Registry64Bit = $true
}
# Collect information about what's under GE Aircraft Engines
try {
$subKeys = Get-ChildItem -Path $basePath -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Name | ForEach-Object { Split-Path $_ -Leaf }
$geInfo.RegistryNotes[$pathType] = @{
BasePath = $basePath
SubKeys = $subKeys -join ', '
Found = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
}
Write-Host " Sub-keys found: $($subKeys -join ', ')" -ForegroundColor Cyan
}
catch {
Write-Host " Error reading sub-keys: $_" -ForegroundColor Red
$geInfo.RegistryNotes[$pathType] = @{
Error = $_.Exception.Message
}
}
# Check for DualPath configuration in eFocas
$efocasPath = "$basePath\DNC\eFocas"
if (Test-Path $efocasPath) {
Write-Host " Checking eFocas configuration for DualPath..." -ForegroundColor Yellow
try {
$efocasValues = Get-ItemProperty -Path $efocasPath -ErrorAction SilentlyContinue
if ($efocasValues.DualPath) {
Write-Host " [FOUND] DualPath = $($efocasValues.DualPath)" -ForegroundColor Green
# Handle case where both registry locations exist - prioritize settings from first found
if ($geInfo.DualPathEnabled -eq $null) {
$geInfo.DualPathEnabled = $efocasValues.DualPath -eq 'YES'
Write-Host " Setting DualPath from $pathType registry: $($geInfo.DualPathEnabled)" -ForegroundColor Cyan
} else {
Write-Host " DualPath already set from other registry location, keeping existing value" -ForegroundColor Yellow
}
# Handle Path1Name - use first non-empty value found
if (!$geInfo.Path1Name -and $efocasValues.Path1Name) {
$geInfo.Path1Name = $efocasValues.Path1Name
Write-Host " Path1Name = $($efocasValues.Path1Name)" -ForegroundColor Cyan
}
# Handle Path2Name - use first non-empty value found
if (!$geInfo.Path2Name -and $efocasValues.Path2Name) {
$geInfo.Path2Name = $efocasValues.Path2Name
Write-Host " Path2Name = $($efocasValues.Path2Name)" -ForegroundColor Cyan
}
# Store additional eFocas settings
$geInfo.RegistryNotes["$pathType-eFocas"] = @{
DualPath = $efocasValues.DualPath
Path1Name = $efocasValues.Path1Name
Path2Name = $efocasValues.Path2Name
IpAddr = $efocasValues.IpAddr
SocketNo = $efocasValues.SocketNo
Danobat = $efocasValues.Danobat
DataServer = $efocasValues.DataServer
}
}
}
catch {
Write-Host " Error reading eFocas configuration: $_" -ForegroundColor Red
}
}
} else {
Write-Host " [NOT FOUND] No GE Aircraft Engines in $pathType registry" -ForegroundColor Gray
}
}
# Summary
Write-Host " GE Registry Summary:" -ForegroundColor Green
Write-Host " 32-bit registry: $(if ($geInfo.Registry32Bit) { 'YES' } else { 'NO' })" -ForegroundColor Cyan
Write-Host " 64-bit registry: $(if ($geInfo.Registry64Bit) { 'YES' } else { 'NO' })" -ForegroundColor Cyan
Write-Host " DualPath enabled: $(if ($geInfo.DualPathEnabled -eq $null) { 'NOT FOUND' } elseif ($geInfo.DualPathEnabled) { 'YES' } else { 'NO' })" -ForegroundColor Cyan
if ($geInfo.Path1Name) { Write-Host " Path1Name: $($geInfo.Path1Name)" -ForegroundColor Cyan }
if ($geInfo.Path2Name) { Write-Host " Path2Name: $($geInfo.Path2Name)" -ForegroundColor Cyan }
return $geInfo
}
# Function to get DNC configuration from registry
function Get-DNCConfig {
Write-Host " Collecting DNC configuration..." -ForegroundColor Yellow
$dncConfig = $null
$paths = @('HKLM:\SOFTWARE\GE Aircraft Engines\DNC\General', 'HKLM:\SOFTWARE\WOW6432Node\GE Aircraft Engines\DNC\General')
Write-Host " Checking registry paths for DNC config..." -ForegroundColor Gray
foreach ($path in $paths) {
Write-Host " Checking path: $path" -ForegroundColor Gray
if (Test-Path $path) {
Write-Host " Path exists! Reading values..." -ForegroundColor Green
try {
$general = Get-ItemProperty -Path $path -ErrorAction SilentlyContinue
$mxPath = $path -replace 'General', 'MX'
$mx = Get-ItemProperty -Path $mxPath -ErrorAction SilentlyContinue
$fmsPath = $path -replace 'General', 'FMS'
$fms = Get-ItemProperty -Path $fmsPath -ErrorAction SilentlyContinue
if ($general) {
Write-Host " Found General config values!" -ForegroundColor Green
$dncConfig = @{
Site = $general.Site
CNC = $general.Cnc
NcIF = $general.NcIF
MachineNo = $general.MachineNo
HostType = $general.HostType
FtpHostPrimary = if ($mx) { $mx.FtpHostPrimary } else { $null }
FtpHostSecondary = if ($mx) { $mx.FtpHostSecondary } else { $null }
FtpAccount = if ($mx) { $mx.FtpAccount } else { $null }
Debug = $general.Debug
Uploads = $general.Uploads
Scanner = $general.Scanner
Dripfeed = $general.Dripfeed
AdditionalSettings = @{
Mode = $general.Mode
'Unit/Area' = $general.'Unit/Area'
DvUpldDir = $general.DvUpldDir
Ncedt = $general.Ncedt
Maint = $general.Maint
ChangeWorkstation = $general.ChangeWorkstation
FMSHostPrimary = if ($fms) { $fms.FMSHostPrimary } else { $null }
FMSHostSecondary = if ($fms) { $fms.FMSHostSecondary } else { $null }
} | ConvertTo-Json -Compress
}
Write-Host " Found DNC config: Site=$($dncConfig.Site), MachineNo=$($dncConfig.MachineNo), CNC=$($dncConfig.CNC)" -ForegroundColor Cyan
Write-Host " DNC Config JSON: $($dncConfig | ConvertTo-Json -Compress)" -ForegroundColor Gray
break
}
}
catch {
Write-Host " Error reading DNC registry: $_" -ForegroundColor Red
}
} else {
Write-Host " Path does not exist" -ForegroundColor Yellow
}
}
if (-not $dncConfig) {
Write-Host " No DNC configuration found in registry" -ForegroundColor Yellow
}
return $dncConfig
}
# Main function to collect all shopfloor configurations
function Get-ShopfloorConfigurations {
Write-Host "`nCollecting shopfloor-specific configurations..." -ForegroundColor Yellow
$configurations = @{
NetworkInterfaces = Get-NetworkInterfaceConfig
CommConfigs = Get-SerialPortConfig
DNCConfig = Get-DNCConfig
GERegistryInfo = Get-GERegistryInfo
}
# Summary
Write-Host "`n Configuration Summary:" -ForegroundColor Green
Write-Host " Network Interfaces: $($configurations.NetworkInterfaces.Count)" -ForegroundColor Cyan
Write-Host " Comm Configs: $($configurations.CommConfigs.Count)" -ForegroundColor Cyan
Write-Host " DNC Config: $(if ($configurations.DNCConfig) { 'Yes' } else { 'No' })" -ForegroundColor Cyan
Write-Host " GE Registry (32-bit): $(if ($configurations.GERegistryInfo.Registry32Bit) { 'Yes' } else { 'No' })" -ForegroundColor Cyan
Write-Host " GE Registry (64-bit): $(if ($configurations.GERegistryInfo.Registry64Bit) { 'Yes' } else { 'No' })" -ForegroundColor Cyan
Write-Host " DualPath Enabled: $(if ($configurations.GERegistryInfo.DualPathEnabled -eq $null) { 'Not Found' } elseif ($configurations.GERegistryInfo.DualPathEnabled) { 'Yes' } else { 'No' })" -ForegroundColor Cyan
return $configurations
}
function Get-InstalledApplications {
<#
.SYNOPSIS
Detects UDC and CLM applications and their active status on shopfloor PCs
.DESCRIPTION
Checks for UDC (UDC.exe) and CLM (ppdcs.exe) processes and returns data
compatible with your existing installedapps table structure.
#>
Write-Host " Scanning for UDC and CLM applications..." -ForegroundColor Yellow
$detectedApps = @()
try {
# Define the two applications we're looking for
$appsToCheck = @{
'UDC' = @{
AppID = 2 # Universal Data Collector
ProcessName = 'UDC' # UDC.exe shows as 'UDC' in Get-Process
Description = 'Universal Data Collector'
}
'CLM' = @{
AppID = 4 # Legacy UDC (CLM)
ProcessName = 'ppdcs' # ppdcs.exe shows as 'ppdcs' in Get-Process
Description = 'Legacy UDC (Cell Level Manager)'
}
}
foreach ($appName in $appsToCheck.Keys) {
$app = $appsToCheck[$appName]
Write-Host " Checking for $appName (AppID: $($app.AppID))..." -ForegroundColor Gray
# Check if the process is running
$isActive = $false
$processInfo = $null
try {
$processes = Get-Process -Name $app.ProcessName -ErrorAction SilentlyContinue
if ($processes) {
$isActive = $true
$processInfo = $processes[0] # Take first instance if multiple
Write-Host " [ACTIVE] Found running process: $($app.ProcessName).exe (PID: $($processInfo.Id))" -ForegroundColor Green
} else {
Write-Host " [NOT ACTIVE] Process $($app.ProcessName).exe not running" -ForegroundColor Gray
}
} catch {
Write-Host " [ERROR] Failed to check process $($app.ProcessName): $($_.Exception.Message)" -ForegroundColor Yellow
}
# Always return app info (both active and inactive)
$detectedApps += @{
AppID = $app.AppID
AppName = $appName
Description = $app.Description
ProcessName = $app.ProcessName
IsActive = $isActive
ProcessID = if ($processInfo) { $processInfo.Id } else { $null }
ProcessStartTime = if ($processInfo) { $processInfo.StartTime } else { $null }
}
}
# Business rule validation: Only one should be active
$activeApps = $detectedApps | Where-Object { $_.IsActive -eq $true }
if ($activeApps.Count -gt 1) {
Write-Host " [WARNING] Multiple applications active simultaneously:" -ForegroundColor Red
foreach ($activeApp in $activeApps) {
Write-Host " - $($activeApp.AppName) (PID: $($activeApp.ProcessID))" -ForegroundColor Red
}
} elseif ($activeApps.Count -eq 1) {
$activeApp = $activeApps[0]
Write-Host " [OK] Single active application: $($activeApp.AppName) (PID: $($activeApp.ProcessID))" -ForegroundColor Green
} else {
Write-Host " [INFO] No UDC or CLM applications currently running" -ForegroundColor Gray
}
return $detectedApps
} catch {
Write-Host " [ERROR] Failed to scan for applications: $($_.Exception.Message)" -ForegroundColor Red
return @()
}
}