diff --git a/fix-nic-powersave.ps1 b/fix-nic-powersave.ps1 new file mode 100644 index 0000000..3bd4075 --- /dev/null +++ b/fix-nic-powersave.ps1 @@ -0,0 +1,95 @@ +# fix-nic-powersave.ps1 - отключение энергосбережения сетевой карты (EEE / Green Ethernet / PnP power). +# TrueGamers: лечит link-флапы с периодом ~5 с (PC20 .120, PC06 .106 и другие машины зала). +# Запуск от Администратора: powershell -ExecutionPolicy Bypass -File fix-nic-powersave.ps1 +# +# 21.09.2026: заменяет fix-realtek-eee.ps1. Тот работал только с Realtek, а в клубе шесть разных +# OUI (18:C0:4D, 10:7C:61, 30:56:0F, D8:5E:D3, 9C:6B:00, 08:BF:B8) — на остальных машинах он +# просто выходил с "адаптеры не найдены". +# +# ВАЖНО: Wake-on-LAN НЕ трогаем. Клуб будит машины по сети, а метрика "порт на 10 Мбит = машина +# выключена" построена ровно на том, что карта держит линк для WoL (см. decisions/2026-09-15- +# truegamers-false-bad-cable-verdict). Поэтому ключи WakeOnMagicPacket / S5WakeOnLan / +# WolShutdownLinkSpeed остаются как есть. +# +# ВНИМАНИЕ: применение кратко роняет линк (2-5 с, адаптер переинициализируется) — +# только на машине, за которой сейчас никто не играет. + +#Requires -RunAsAdministrator + +# Ключи реестра, а не подписи в UI: имена свойств локализованы, ключи — нет. +$keywords = @( + '*EEE', # стандартный ключ Energy Efficient Ethernet + 'EnableEee', # Realtek + 'AdvancedEEE', # Realtek + 'EnableGreenEthernet', # Realtek Green Ethernet + 'GigaLite', # Realtek Gigabit Lite + 'EEELinkAdvertisement', # анонс EEE при автосогласовании + 'AutoDisableGigabit', # авто-понижение скорости при простое + 'PowerSavingMode', # общий режим энергосбережения + 'ULPMode', # Ultra Low Power (Intel/Killer) + 'EnableDynamicPowerGating', + 'AutoPowerSaveModeEnabled' +) + +$nics = Get-NetAdapter -Physical -ErrorAction SilentlyContinue | + Where-Object { $_.Virtual -ne $true } +if (-not $nics) { + Write-Host "Физические сетевые адаптеры не найдены." + exit 1 +} + +foreach ($nic in $nics) { + Write-Host ("=" * 60) + Write-Host ("Адаптер: " + $nic.Name + " | " + $nic.InterfaceDescription + " | " + $nic.Status + " | " + $nic.LinkSpeed) + + # 1) Галка "Разрешить отключение этого устройства для экономии энергии" + try { + Disable-NetAdapterPowerManagement -Name $nic.Name -NoRestart -ErrorAction Stop + Write-Host "[OK] PnP-энергосбережение адаптера отключено" + } catch { + Write-Host ("[WARN] Disable-NetAdapterPowerManagement: " + $_.Exception.Message) + } + + # 2) Свойства драйвера + $touched = $false + foreach ($kw in $keywords) { + $cur = Get-NetAdapterAdvancedProperty -Name $nic.Name -RegistryKeyword $kw -ErrorAction SilentlyContinue + if (-not $cur) { continue } + $before = $cur.DisplayValue + if ($cur.RegistryValue -contains '0' -or $before -eq 'Disabled') { + Write-Host ("[..] " + $kw + " уже выключен") + continue + } + try { + Set-NetAdapterAdvancedProperty -Name $nic.Name -RegistryKeyword $kw -RegistryValue 0 -NoRestart -ErrorAction Stop + Write-Host ("[OK] " + $kw + ": '" + $before + "' -> Disabled") + $touched = $true + } catch { + Write-Host ("[WARN] " + $kw + " не удалось выставить: " + $_.Exception.Message) + } + } + + # -NoRestart выше копит изменения, чтобы адаптер дёрнулся ОДИН раз, а не после каждого ключа + if ($touched) { + Write-Host "[..] перезапуск адаптера (линк моргнёт на пару секунд)" + try { + Restart-NetAdapter -Name $nic.Name -ErrorAction Stop + } catch { + Write-Host ("[WARN] Restart-NetAdapter: " + $_.Exception.Message) + } + } +} + +Write-Host ("=" * 60) +Write-Host "Итог через 8 секунд:" +Start-Sleep -Seconds 8 +Get-NetAdapter -Physical | Where-Object { $_.Virtual -ne $true } | ForEach-Object { + $vals = @() + foreach ($kw in $keywords) { + $p = Get-NetAdapterAdvancedProperty -Name $_.Name -RegistryKeyword $kw -ErrorAction SilentlyContinue + if ($p) { $vals += ($kw + "=" + $p.DisplayValue) } + } + $wol = Get-NetAdapterAdvancedProperty -Name $_.Name -RegistryKeyword 'WakeOnMagicPacket' -ErrorAction SilentlyContinue + Write-Host ($_.Name + " | " + $_.Status + " | " + $_.LinkSpeed + " | " + ($vals -join ", ") + + " | WoL=" + $(if ($wol) { $wol.DisplayValue } else { 'n/a' })) +}