Reputation: 11
What I'm trying to do is write a PowerShell script that checks every 60 seconds the availability of internet connections on the Ethernet and Wi-Fi adapters by pinging 8.8.8.8 on each adapter.
Based on the availability, it changes the metrics of the adapters to prioritize the one with an active internet connection.
If both adapters have internet, it sets the Ethernet adapter as the default.
If only the Ethernet adapter has internet, it keeps it as the default. If only the Wi-Fi adapter has internet, it changes the metrics to switch to Wi-Fi.
If neither adapter has an active internet connection, it sets the metrics to default.
This way, I don't have to unplug the ethernet cable or disable the adapter for it to switch to Wi-Fi when ethernet loses internet connection.
It's not accepting the -InterfaceAlias
parameter in the Test-Connection
command
Test-Connection:
Line |
8 | … est-Connection -ComputerName 8.8.8.8 -Count 1 -InterfaceAlias $Ethern …
| ~~~~~~~~~~~~~~~
| A parameter cannot be found that matches parameter name 'InterfaceAlias'.
Test-Connection:
Is there any way to fix this or any other approach to reach my goal?
function Set-InternetPriority {
param (
[string]$EthernetAdapterName,
[string]$WiFiAdapterName
)
# Check if Ethernet adapter is connected to the internet
$ethernetPingResult = Test-Connection -ComputerName 8.8.8.8 -Count 1 -InterfaceAlias $EthernetAdapterName -Quiet
# Check if Wi-Fi adapter is connected to the internet
$wifiPingResult = Test-Connection -ComputerName 8.8.8.8 -Count 1 -InterfaceAlias $WiFiAdapterName -Quiet
# Set the metrics based on the availability of internet connections
if ($ethernetPingResult -and $wifiPingResult) {
# Both adapters have internet, set Ethernet as default
Write-Output "Both Ethernet and Wi-Fi adapters have an internet connection."
Write-Output "Setting Ethernet adapter as the default."
Set-NetIPInterface -InterfaceAlias $EthernetAdapterName -InterfaceMetric 10
Set-NetIPInterface -InterfaceAlias $WiFiAdapterName -InterfaceMetric 20
}
elseif ($ethernetPingResult) {
# Only Ethernet has internet, keep it as default
Write-Output "Only Ethernet adapter has an internet connection."
Write-Output "Keeping Ethernet adapter as the default."
Set-NetIPInterface -InterfaceAlias $EthernetAdapterName -InterfaceMetric 10
Set-NetIPInterface -InterfaceAlias $WiFiAdapterName -InterfaceMetric 100
}
elseif ($wifiPingResult) {
# Only Wi-Fi has internet, switch to Wi-Fi
Write-Output "Only Wi-Fi adapter has an internet connection."
Write-Output "Switching to Wi-Fi adapter."
Set-NetIPInterface -InterfaceAlias $EthernetAdapterName -InterfaceMetric 100
Set-NetIPInterface -InterfaceAlias $WiFiAdapterName -InterfaceMetric 10
}
else {
# Neither adapter has internet, set metrics to default
Write-Output "Neither Ethernet nor Wi-Fi adapter has an internet connection."
Write-Output "Setting metrics to default."
Set-NetIPInterface -InterfaceAlias $EthernetAdapterName -InterfaceMetric 10
Set-NetIPInterface -InterfaceAlias $WiFiAdapterName -InterfaceMetric 20
}
}
# Infinite loop to keep checking and setting metrics every 60 seconds
while ($true) {
Set-InternetPriority -EthernetAdapterName "Ethernet" -WifiAdapterName "Wi-Fi"
# Delay for 60 seconds
Start-Sleep -Seconds 60
}
I tried several other ways through using the ping command and Test-NetConnection
command and my brain is just hurting right now.
Upvotes: 1
Views: 569
Reputation: 11
Since I wanted to only switch adapters if one loses connection not if it has a slower connection I was struggling, but sometimes the easiest option is the one lying in front of our eyes, isn't it? I eventually got my code to work by using the ping cmdlet through each adapter and capturing its output. As stated in this post The first IP is the IP to ping (duh) second IP is the source address IP, the IP of the wanted network adapter.
ping 8.8.8.8 -l 0 -S 192.168.0.124
This is the working somewhat polished code of a script that monitors the internet connectivity of specified network adapters by pinging through their IP address, if anyone ever needs it.
# Function to check if there is an active internet connection
function Test-InternetConnection {
param (
[string]$Adapter
)
$pingCommand = "ping 8.8.8.8 -l 0 -S $Adapter"
$pingOutput = Invoke-Expression -Command $pingCommand
return $pingOutput -match "Reply from 8.8.8.8"
}
# Function to set network adapter metrics
function Set-NetworkAdapterMetrics {
param (
[string]$EthernetAdapter,
[string]$WiFiAdapter
)
# Check internet connection through Ethernet
$ethernetConnected = Test-InternetConnection -Adapter $EthernetAdapter
# Check internet connection through Wi-Fi
$wifiConnected = Test-InternetConnection -Adapter $WiFiAdapter
if ($ethernetConnected -and $wifiConnected) {
# Both adapters have internet, set Ethernet as default
Write-Host "Both adapters have internet. Setting Ethernet as default." -ForegroundColor Blue
Set-NetIPInterface -InterfaceAlias $EthernetAdapterName -InterfaceMetric 1
Set-NetIPInterface -InterfaceAlias $WiFiAdapterName -InterfaceMetric 20
} elseif ($ethernetConnected) {
# Only Ethernet has internet, keep it as default
Write-Host "Only Ethernet has internet. Keeping it as default." -ForegroundColor Blue
Set-NetIPInterface -InterfaceAlias $EthernetAdapterName -InterfaceMetric 1
Set-NetIPInterface -InterfaceAlias $WiFiAdapterName -InterfaceMetric 20
} elseif ($wifiConnected) {
# Only Wi-Fi has internet, switch to Wi-Fi
Write-Host "Only Wi-Fi has internet. Switching to Wi-Fi." -ForegroundColor Magenta
Set-NetIPInterface -InterfaceAlias $EthernetAdapterName -InterfaceMetric 20
Set-NetIPInterface -InterfaceAlias $WiFiAdapterName -InterfaceMetric 1
} else {
# Neither adapter has internet, set metrics to default
Write-Host "Neither adapter has internet. Setting metrics to default." -ForegroundColor Red
Set-NetIPInterface -InterfaceAlias $EthernetAdapterName -InterfaceMetric 10
Set-NetIPInterface -InterfaceAlias $WiFiAdapterName -InterfaceMetric 20
}
}
# Specify the IP Addresses and names of the network adapters for Ethernet and Wi-Fi
$ethernetAdapterIP = "192.168.0.142"
$wifiAdapterIP = "192.168.0.124"
$ethernetAdapterName = "Ethernet"
$wifiAdapterName = "Wi-Fi"
Write-Host "Press Enter to start the script" -ForegroundColor Yellow
$null = Read-Host
Write-Host "Network Adapter Metrics script has started `nIt will check the adapters every 60 seconds." -ForegroundColor Green
Write-Host "Press ctrl-c to stop.`n" -ForegroundColor Cyan
# Loop until you manually stop the script
while ($true) {
Set-NetworkAdapterMetrics -EthernetAdapter $ethernetAdapterIP -WiFiAdapter $wifiAdapterIP -EthernetAdapterName $ethernetAdapterName -WiFiAdapterName $wifiAdapterName
Start-Sleep -Seconds 60
}
I'd like some feedback on this if it is overkill or if there is a better way to achieve it. Other than that it works just fine.
Upvotes: 0
Reputation: 4694
I think a better approach to this is using Get-NetRoute
, since it allows you to see and understand which connection (Ethernet or Wi-Fi) your computer is currently favoring for its internet traffic.
So, if the computer's map (routing table) points to Ethernet, it means Ethernet is the favored path for the internet. If it points to Wi-Fi, then Wi-Fi is the preference. And because computers are smart, the routing table will often automatically prioritize a connection that's active and stable. So, if Ethernet isn't working well, but Wi-Fi is, the computer will likely set Wi-Fi as the preferred path without you doing anything. By checking with Get-NetRoute
, you can see this choice in action.
Personally, I would write it like this instead:
function Get-InternetInterface {
# Find the default route (0.0.0.0)
$default_route = Get-NetRoute | Where-Object { $_.DestinationPrefix -eq '0.0.0.0/0' } | Sort-Object RouteMetric | Select-Object -First 1
# If a default route was found, get the associated network adapter
if ($default_route)
{
Get-NetAdapter | Where-Object { $_.InterfaceIndex -eq $default_route.InterfaceIndex }
}
return $null
}
function Set-InternetPriority {
Param(
[string]$EthernetAdapterName = "Ethernet",
[string]$WiFiAdapterName = "Wi-Fi"
)
$internet_interface = Get-InternetInterface
# Define default metrics
$ethernet_metric = 10
$wifi_metric = 20
if ($internet_interface.Name -eq $WiFiAdapterName)
{
# Swap metrics if Wi-Fi is the active connection
$ethernet_metric, $wifi_metric = $wifi_metric, $ethernet_metric
}
Set-NetIPInterface -InterfaceAlias $EthernetAdapterName -InterfaceMetric $ethernet_metric
Set-NetIPInterface -InterfaceAlias $WiFiAdapterName -InterfaceMetric $wifi_metric
}
# Continuous loop to adjust metrics
while ($true)
{
try
{
Set-InternetPriority
}
catch
{
# Handle or log the error if needed
Write-Error "An error occurred: $_"
}
Start-Sleep -Seconds 60
}
Where we have a helper function Get-InternetInterface
to check the routing table, and a cleaner approach for Set-InternetPriority
based on that.
Upvotes: 0