From 00d4105956939e162740deb4fdae82fe8c3dea8a Mon Sep 17 00:00:00 2001 From: cproudlock Date: Sun, 24 May 2026 07:04:02 -0400 Subject: [PATCH] 04-SetControllerNicIP: broaden adapter enum + store-mismatch fix + netsh fallback - Drop -Physical + MediaType filter from Get-NetAdapter; some OEM driver stacks report HardwareInterface=False or localize MediaType, hiding the Realtek controller NIC from the previous query. - Refine corp-vs-controller classification: skip only if a gateway is set AND it's not 192.168.1.x, OR if the IP looks corp (10.x / 172.16-31.x). Keep candidates that are unconfigured, link-local, or 192.168.x. - Disable DHCP in both PersistentStore and ActiveStore before New-NetIPAddress to avoid "Inconsistent parameters PolicyStore PersistentStore and Dhcp enabled" failures. - Fall back to netsh interface ip set address when the PS cmdlets still fight each other; netsh writes both stores cleanly. --- .../04-SetControllerNicIP.ps1 | 80 +++++++++++++++---- 1 file changed, 63 insertions(+), 17 deletions(-) diff --git a/playbook/shopfloor-setup/gea-shopfloor-collections/04-SetControllerNicIP.ps1 b/playbook/shopfloor-setup/gea-shopfloor-collections/04-SetControllerNicIP.ps1 index a807465..a0076d0 100644 --- a/playbook/shopfloor-setup/gea-shopfloor-collections/04-SetControllerNicIP.ps1 +++ b/playbook/shopfloor-setup/gea-shopfloor-collections/04-SetControllerNicIP.ps1 @@ -42,12 +42,20 @@ $prefixLen = 24 Write-NicLog "=== 04-SetControllerNicIP start ===" -# Enumerate physical Ethernet adapters with Realtek in the vendor description. -$candidates = Get-NetAdapter -Physical -ErrorAction SilentlyContinue | - Where-Object { $_.InterfaceDescription -match 'Realtek' -and $_.MediaType -eq '802.3' } +# Enumerate ALL adapters first, then filter. Don't use -Physical: on some +# OEM driver stacks the Realtek NIC reports HardwareInterface=False and +# would be excluded. Don't filter on MediaType either: some drivers report +# '802.3' as a localized string or as the numeric '6'. +$allAdapters = Get-NetAdapter -ErrorAction SilentlyContinue +Write-NicLog "All adapters on this machine:" +foreach ($a in $allAdapters) { + Write-NicLog " $($a.Name) ifIndex=$($a.ifIndex) desc='$($a.InterfaceDescription)' status=$($a.Status) mediatype='$($a.MediaType)' physical='$($a.HardwareInterface)'" +} -if (-not $candidates) { - Write-NicLog "No Realtek physical Ethernet adapters found - nothing to configure (PC may have no controller NIC)." +$candidates = @($allAdapters | Where-Object { $_.InterfaceDescription -match 'Realtek' }) + +if (-not $candidates -or $candidates.Count -eq 0) { + Write-NicLog "No Realtek adapters found - nothing to configure (PC may have no controller NIC)." exit 0 } @@ -56,8 +64,10 @@ foreach ($c in $candidates) { Write-NicLog " $($c.Name) ($($c.InterfaceDescription)) [status=$($c.Status)]" } -# Filter out anything that already looks like the corp LAN NIC (has a -# DHCP-assigned default gateway -- corp DHCP servers always hand one out). +# Filter out the corp-LAN Realtek (if any): has a DHCP-assigned default +# gateway (corp DHCP always hands one out) OR has an IP in a corp subnet +# (10.x / non-192.168.1.x). Keep candidates that are unconfigured (link-local +# / no IP / 192.168.x). $filtered = @() foreach ($c in $candidates) { $ipCfg = Get-NetIPConfiguration -InterfaceIndex $c.ifIndex -ErrorAction SilentlyContinue @@ -65,16 +75,31 @@ foreach ($c in $candidates) { if ($ipCfg -and $ipCfg.IPv4DefaultGateway) { $gw = ($ipCfg.IPv4DefaultGateway | Select-Object -First 1).NextHop } - if ($gw) { - Write-NicLog " Skipping $($c.Name) - has IPv4 default gateway $gw (likely corp LAN, not controller)" + $v4 = @() + if ($ipCfg -and $ipCfg.IPv4Address) { + $v4 = @($ipCfg.IPv4Address | ForEach-Object { $_.IPAddress }) + } + Write-NicLog " $($c.Name): ips=$($v4 -join ',') gw=$gw" + + # Already has the target IP -> done. + if ($v4 -contains $targetIP) { + Write-NicLog " Skipping $($c.Name) - already has $targetIP/$prefixLen (configured previously)" continue } - # Skip if it already has 192.168.1.2 - already configured. - $existing = Get-NetIPAddress -InterfaceIndex $c.ifIndex -AddressFamily IPv4 -ErrorAction SilentlyContinue | - Where-Object { $_.IPAddress -eq $targetIP } - if ($existing) { - Write-NicLog " Skipping $($c.Name) - already has $targetIP/$prefixLen (configured previously)" + # Has a default gateway AND that gateway is NOT 192.168.1.x -> corp LAN, skip. + if ($gw -and ($gw -notmatch '^192\.168\.1\.')) { + Write-NicLog " Skipping $($c.Name) - has non-controller IPv4 default gateway $gw (likely corp LAN)" + continue + } + + # Has a corp-style IP (10.x or 172.16-31.x) -> corp LAN, skip. + $isCorp = $false + foreach ($ip in $v4) { + if ($ip -match '^10\.' -or $ip -match '^172\.(1[6-9]|2[0-9]|3[01])\.') { $isCorp = $true; break } + } + if ($isCorp) { + Write-NicLog " Skipping $($c.Name) - has corp-subnet IP $($v4 -join ',') (not the controller NIC)" continue } @@ -108,14 +133,35 @@ try { } # Switch the interface to manual IP assignment + set the static. +# +# Windows store-mismatch trap: Set-NetIPInterface defaults to ActiveStore, +# New-NetIPAddress defaults to PersistentStore. If we only disable DHCP in +# ActiveStore, New-NetIPAddress fails with: +# "Inconsistent parameters PolicyStore PersistentStore and Dhcp enabled" +# Disable DHCP in BOTH stores first, then add the static IP. If the +# cmdlets still fight us, fall back to netsh (writes both stores cleanly). +$staticSet = $false try { - Set-NetIPInterface -InterfaceIndex $target.ifIndex -Dhcp Disabled -ErrorAction Stop + Set-NetIPInterface -InterfaceIndex $target.ifIndex -Dhcp Disabled -PolicyStore PersistentStore -ErrorAction SilentlyContinue + Set-NetIPInterface -InterfaceIndex $target.ifIndex -Dhcp Disabled -PolicyStore ActiveStore -ErrorAction SilentlyContinue New-NetIPAddress -InterfaceIndex $target.ifIndex -IPAddress $targetIP ` -PrefixLength $prefixLen -ErrorAction Stop | Out-Null Write-NicLog "Set $targetIP/$prefixLen on $($target.Name) (no gateway)" + $staticSet = $true } catch { - Write-NicLog "Failed to set static IP on $($target.Name): $_" 'ERROR' - exit 1 + Write-NicLog "PowerShell static IP set failed: $_ -- falling back to netsh" 'WARN' +} + +if (-not $staticSet) { + $mask = '255.255.255.0' + $netshOut = & netsh interface ip set address name="$($target.Name)" static $targetIP $mask 2>&1 + if ($LASTEXITCODE -eq 0) { + Write-NicLog "netsh set $targetIP/$mask on $($target.Name)" + $staticSet = $true + } else { + Write-NicLog "netsh failed too: $netshOut" 'ERROR' + exit 1 + } } # Clear DNS so the corp resolver doesn't get queried for controller-side hostnames.