Windows双网卡自动切换脚本实战:路由表、DNS与批处理/PowerShell实现
2026/9/16 20:58:08 网站建设 项目流程

1. 双网卡切换,为什么值得写个脚本

1.1 最常见的几类双网卡场景

我做了多年桌面运维和网络支持,遇到“双网卡”的频率比想象中高得多。最常见的是三类场景。

第一类是内网和外网隔离。办公网里存着内部系统、文件服务器、打印机,另一张网卡接的是宽带或手机开的热点,用于互联网访问。有些团队为了安全要求,明确规定这两条链路不能同时在线,员工每天要在两种模式之间来回切。第二类是研发和测试环境。机器一台连着办公网络,另一张无线网卡要连到设备调试网段,或者连到一台临时搭的路由器上,每次切换都涉及 IP、网关、DNS 全套参数。第三类是有线和无线互为备份。无线信号不稳定时切到有线,有线被拔掉时切回无线,虽然不频繁,但一旦要切,通常都是赶时间的时候。

不管是哪类场景,本质问题都一样:一台电脑上有两张可用网卡,但同一时刻只能以其中一种网络配置作为主链路。命令行脚本存在的意义,就是把“禁用一块网卡、启用另一块、重置路由、刷新 DNS、验证连通性”这一连串操作合并成一次执行。

1.2 手动切网到底慢在哪

在图形界面里手动切换一次,步骤大致是这样的:右键网络图标、进入网络适配器选项、找到目标网卡、右键禁用或启用、再进入 IPv4 属性、改 IP 和网关、有时还要改 DNS、最后打开命令行执行ipconfig /flushdns。整套流程顺利的话也要一分钟,稍微一犹豫,或者系统网络服务卡一下,三五分钟都很正常。

比慢更麻烦的是容易出错。公司内部网络如果用的静态 IP,你得记住那串数字;如果 DHCP 获取,还要等它超时。最恼火的是两张网卡都处于启用状态时,系统会同时看到两个默认网关,它可能继续走旧的网卡,结果就是你感觉自己切过去了,实际上访问内网资源还是不通。这种状态特别难排查,因为你刚改完 IP,桌面右下角的网络图标看起来是正常的,但路由表里早就乱套了。

1.3 脚本化能解决什么

把切换动作写进脚本后,解决的问题不只是快。更关键的是确定性。每次执行都是同一套参数、同一个顺序,不会因为手抖改错一位 IP;切换完还能自动验证,通了就在屏幕上显示结果,没通则提示失败。再有就是可以交给别人执行。很多同事对网络设置并不熟,他们只需要双击一个切换入口,然后告诉我切完了,剩下的事由脚本保证。

所以我不建议用临时的“手输命令”来应对高频切换。整理成脚本,本质上是把一次性的操作变成可重复、可维护、可交接的资产。

2. 动手前先搞懂路由表和网络优先级

2.1 电脑是怎么决定数据走哪张网卡的

要理解双网卡切换,必须先看路由表。很多人以为切换网卡就是“启用哪块用哪块”,实际上操作系统是查路由表来决定数据包交给哪块网卡的。

在命令行里输入route print -4,你会看到一张 IPv4 路由表,核心是这么几列:

网络目标 网络掩码 网关 接口 跃点数 0.0.0.0 0.0.0.0 192.168.1.1 192.168.1.100 35 0.0.0.0 0.0.0.0 10.10.20.1 10.10.20.5 30 10.10.20.0 255.255.255.0 On-link 10.10.20.5 276 192.168.1.0 255.255.255.0 On-link 192.168.1.100 291

其中0.0.0.0那两条是默认路由,代表“所有不知道往哪走的数据包都交给它”。如果两条默认路由同时存在,系统会优先选择“跃点数”更小的那条。比如上面表格里走内网网关的默认路由跃点数是 30,走外网网关的是 35,那么所有上网流量会优先走内网。听起来可能没问题,但假如你现在想访问互联网,流量却被送往内网网关,内网网关没有互联网出口,数据就丢了。

所以双网卡切换脚本里的一项重要工作,就是管理默认路由。要么把不需要的默认路由删掉,要么把目标网卡的默认路由跃点数调成最小,确保切完之后,默认流量只会走当前想要走的那张网卡。

2.2 网卡状态、IP 配置、路由跃点有什么关系

三者其实是联动的。禁用一块网卡后,它的所有路由条目都会从路由表里消失;启用网卡后,系统会根据网卡上配置的 IP、子网掩码、网关自动生成直连路由和默认路由。也就是说,只改路由理论上是可行的,但网卡状态不改变,系统可能会在某个时刻因为 DHCP 续租或网络状态变化重新生成一条你不想看到的路由。

手动切换最容易漏掉的就是这一点。你在网络连接面板里把有线网卡禁用了,但无线网卡迟迟没拿到地址,或者默认路由还残留着有线网卡的信息,网络状态就会很混乱。脚本的做法通常是一套组合拳:先禁用当前不需要的网卡,再启用目标网卡,然后清理默认路由,最后手动添加一条稳定的默认路由,并指定它的跃点数。

顺带说一下移动网络的自动跃点机制。Windows 默认会给接口开启自动跃点,系统根据链路速度等参数自动计算。这很方便,但在双网卡场景下,自动计算的结果不一定符合你的期望,所以脚本里最好手动指定跃点数。跃点数只表示优先级,数字不一定是越小越“快”,它只是让系统知道哪条路由优先使用。

2.3 为什么切换后经常出现“网络假通”

最常见的“假通”现象是:右下角网络图标显示已连接,但访问公司内网服务器超时。原因多半是默认路由还指在不该指的网卡上,或者 DNS 用的还是另一张网卡下发的地址。

DNS 这个问题很隐蔽。即使你把默认路由切过去了,如果网卡上配置的 DNS 还是旧网络下的地址,解析域名时还是会失败。所以我的脚本里一般都会顺手把 DNS 也设好,或者至少执行一次ipconfig /flushdns清理缓存。切换后验证不要只 ping 网关,还要同时验证 DNS 解析和实际访问,才能真正确认“切换成功”。

3. 方案选型:批处理还是 PowerShell

3.1 两种脚本怎么选

写 Windows 下的命令行脚本,主要就两个选择:传统批处理(.bat/.cmd)和 PowerShell(.ps1)。我做过一个对比,方便你按自己的环境来选:

对比项批处理PowerShell
系统兼容性Windows 7 到 11 都很好Windows 7 SP1 之后可用,但越新的系统越友好
语法复杂度简单直接,容易上手初看比较复杂,但逻辑更清晰
错误处理弱,出错继续往下走强,可以 catch 异常
网卡操作netsh间接操作有专门的NetAdapter模块
适合人群老运维、快速写小工具有条件写更复杂逻辑的人

如果你只是需要“双击运行、马上切换”,批处理完全够用。但如果你想做更复杂的判断,比如“先 ping 网关,通了才切换”或者“切换失败自动回滚”,PowerShell 写起来更顺手。我的建议是,老机器、老系统上部署,优先批处理;自己维护的机器或者公司标准环境是 Windows 10 以上,直接上 PowerShell,后续扩展空间更大。

3.2 先把环境信息摸清楚

写脚本之前,必须先确认三件事:网卡叫什么名字、当前 IP 网段是什么、路由表和接口索引长什么样。

看网卡名称最直接的方式是Get-NetAdapter

Get-NetAdapter | Format-Table Name, InterfaceDescription, Status, LinkSpeed

中文系统里,有线网卡通常叫“以太网”,无线网卡通常叫“WLAN”;英文系统一般叫EthernetWi-Fi。这个名字不固定,取决于网卡驱动和系统设置。建议在脚本里写成变量,方便以后改。

查看路由表和接口索引用route print -4,开头部分会列出所有接口列表,里面会有每个接口的 IDX 编号,比如:

接口列表 12...a1 b2 c3 d4 e5 f6 ......Intel(R) Ethernet Connection 8...11 22 33 44 55 66 ......Intel(R) Dual Band Wireless-AC 8265

这个 IDX 编号在后面指定路由时必须用到。

3.3 权限和脚本执行策略,提前准备好

修改网卡状态和路由表,必须要有管理员权限。直接双击批处理,通常会用普通权限跑,所以脚本内部最好第一件事就检查权限,没有权限就直接退出,别让它执行到一半报一堆不明不白的错。

PowerShell 还有一层执行策略限制。默认情况下.ps1文件可能会被系统拦截,运行报错“因为在此系统上禁止运行脚本”。解决办法是给当前用户放开限制,但没必要改成不受限制,用这个命令就够了:

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

设置完以后,本地创建的脚本可以运行,从网上下载的脚本如果没签名则会被拦截,兼顾安全和便利。这些前置工作都说清楚以后,就可以进入正题写脚本了。

4. 完整脚本实现与关键参数说明

4.1 批处理版:适合快速部署的一键切换脚本

先给出一个可以直接用的批处理版本。这个脚本实现“内网模式”和“外网模式”的切换,假设有线网卡叫“以太网”,无线网卡叫“WLAN”,内网网关是 10.10.20.1,外网网关是 192.168.1.1。保存时注意,中文系统下批处理建议用 GBK 编码保存,避免注释和提示文字乱码。

@echo off chcp 65001 >nul net session >nul 2>&1 if %errorlevel% neq 0 ( echo 请以管理员身份运行本脚本。 pause exit /b 1 ) set MODE=%1 if "%MODE%"=="" ( echo 用法: switch-net.bat [intranet^|internet] pause exit /b 1 ) if /i "%MODE%"=="intranet" ( echo 正在切换到内网模式... netsh interface set interface "WLAN" disabled netsh interface set interface "以太网" enabled route delete 0.0.0.0 mask 0.0.0.0 route add 0.0.0.0 mask 0.0.0.0 10.10.20.1 metric 20 ipconfig /flushdns >nul echo 内网模式切换完成。 ) else if /i "%MODE%"=="internet" ( echo 正在切换到外网模式... netsh interface set interface "以太网" disabled netsh interface set interface "WLAN" enabled route delete 0.0.0.0 mask 0.0.0.0 route add 0.0.0.0 mask 0.0.0.0 192.168.1.1 metric 20 ipconfig /flushdns >nul echo 外网模式切换完成。 ) else ( echo 未知模式: %MODE% echo 用法: switch-net.bat [intranet^|internet] ) pause

这里有两处关键点。第一处是route delete 0.0.0.0 mask 0.0.0.0,它会删掉当前所有默认路由。注意,如果你有多张网卡同时在线,删除默认路由后所有网卡的默认路由都会被删掉,然后再统一添加一条我们想要的。

第二处是route add 0.0.0.0 mask 0.0.0.0 10.10.20.1 metric 20,这里的metric 20会让这条路由有比较高的优先级。如果你还需要同时保留另一张网卡的直连网段访问,可以追加静态路由,但大多数人只是切主链路,所以默认路由覆盖掉就够了。

4.2 PowerShell 版:逻辑更清晰,适合扩展

PowerShell 版本对初学者稍难一点,但可读性和可维护性明显更好。脚本同样实现两种模式,并把网卡名和路由参数抽成变量,以后改起来不用翻到命令中间去找。

param( [Parameter(Mandatory=$true)] [ValidateSet("intranet", "internet")] [string]$Mode ) $ErrorActionPreference = "Stop" $admin = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator ) if (-not $admin) { Write-Host "请以管理员身份运行" -ForegroundColor Red exit 1 } $Ethernet = "以太网" $Wlan = "WLAN" switch ($Mode) { "intranet" { Disable-NetAdapter -Name $Wlan -Confirm:$false Enable-NetAdapter -Name $Ethernet -Confirm:$false Get-NetRoute -DestinationPrefix "0.0.0.0/0" | Remove-NetRoute -Confirm:$false New-NetRoute -DestinationPrefix "0.0.0.0/0" -InterfaceAlias $Ethernet -NextHop "10.10.20.1" -RouteMetric 20 Set-DnsClientServerAddress -InterfaceAlias $Ethernet -ServerAddresses "10.10.20.1" Clear-DnsClientCache Write-Host "已切换到内网模式" -ForegroundColor Green } "internet" { Disable-NetAdapter -Name $Ethernet -Confirm:$false Enable-NetAdapter -Name $Wlan -Confirm:$false Get-NetRoute -DestinationPrefix "0.0.0.0/0" | Remove-NetRoute -Confirm:$false New-NetRoute -DestinationPrefix "0.0.0.0/0" -InterfaceAlias $Wlan -NextHop "192.168.1.1" -RouteMetric 20 Set-DnsClientServerAddress -InterfaceAlias $Wlan -ServerAddresses "223.5.5.5" Clear-DnsClientCache Write-Host "已切换到外网模式" -ForegroundColor Green } }

PowerShell 的优势集中在三处:ValidateSet限制了参数只能填intranetinternet,少敲错一个字母;Disable-NetAdapterEnable-NetAdapter这类命令比netsh interface set更直观;$ErrorActionPreference = "Stop"让脚本在出错时停下,而不是蒙着头继续跑。

有一点需要特别说明:如果脚本要放在共享位置或者作为计划任务运行,注意网卡名的空格和中文,-InterfaceAlias直接用字符串就行,不用转义。另外,New-NetRoute-NextHop是网关地址,-RouteMetric是跃点数,这两个参数和批处理版里的route add是对应的。

4.3 route add 里的 if 和 metric 到底怎么填

很多人第一次看route add的帮助文档会被if参数弄晕。它的作用是指定路由绑定到哪个接口。在某些情况下,不写if也可以,但那是系统有明确的“最优接口”时才可靠;在双网卡竞争时,一定要显式指定,否则即使网关是对的,系统也可能把数据包交给错误的网卡。

怎么看接口索引?执行route print -4,最上方就有接口列表。假设有线网卡接口索引是 12,那么添加内网默认路由的命令可以写成:

route add 0.0.0.0 mask 0.0.0.0 10.10.20.1 if 12 metric 20

metric在 Windows 中默认是自动计算的,但手动指定能确保优先级。逻辑上,你想要用的网卡,跃点数设小一点;不常用的网卡,跃点数设大一点。这样即使两块网卡都开着,系统也会优先走你要的那条默认路由。

如果觉得接口索引在重启后可能变化,可以在批处理里先用netsh interface ip show config查看当前名称,再配合route print人工核对。更一劳永逸的做法是直接给网卡命名固定,比如把有线网卡改名为LAN,无线网卡改名为WIFI,脚本里就用这两个名称。

4.4 加日志、加提示、加隐藏运行

脚本跑起来没有反馈,是最容易被忽略的问题。我习惯在批处理里输出一条时间戳日志:

echo [%date% %time%] 切换到内网模式 >> D:\scripts\net-switch.log

PowerShell 版本可以用Add-Content

Add-Content -Path "D:\scripts\net-switch.log" -Value "[$(Get-Date)] 切换到 $Mode 模式"

日志不用写得很复杂,记录“什么时候、切到了什么模式”就够了。万一以后有人问你“网络是谁弄坏的”,翻一下日志立刻能定位。

再有一个实用技巧是隐藏运行窗口。如果脚本是通过计划任务触发,或者你想做成一个完全无感的双击工具,不希望命令行窗口一直弹出来,可以用一个 VBS 脚本包裹执行,窗口模式设为 0:

Set ws = CreateObject("Wscript.Shell") ws.Run "powershell -NoProfile -ExecutionPolicy Bypass -File D:\scripts\switch-net.ps1 intranet", 0, True

把这段存成switch-intranet.vbs,双击时 PowerShell 窗口不会闪出来,但会静默执行。注意这里用了0表示隐藏窗口,True表示等待执行完成后再退出。缺点是一旦出错,你也不知道发生了什么,所以隐藏运行的方案最好搭配日志一起用。

5. 实战操作流程:从部署到验证

5.1 一个典型测试环境

为了把整个流程讲清楚,我以手头一台测试笔记本为例,它的环境长这样:

网卡网络类型IP 配置网关DNS
以太网内网办公静态 IP 10.10.20.5/2410.10.20.110.10.20.1
WLAN互联网DHCP 自动获取192.168.1.1223.5.5.5

目标模式也很清晰:切到“内网模式”时,停用无线网卡,启用有线网卡,默认路由指到内网网关;切到“外网模式”时,停用有线网卡,启用无线网卡,默认路由指到路由器网关。这样设计模式的好处是不会冲突,因为同时只有一张网卡在线。

5.2 部署脚本的具体步骤

第一步,在D:\scripts目录下创建switch-net.ps1,把上面的 PowerShell 脚本保存进去。

第二步,给当前用户开放执行策略:

Set-ExecutionPolicy RemoteSigned -Scope CurrentUser

第三步,建一个桌面快捷方式,目标填:

powershell -NoProfile -ExecutionPolicy Bypass -File D:\scripts\switch-net.ps1 intranet

第四步,快捷方式属性里勾选“以管理员身份运行”。这一步很容易漏,如果你不想每次弹 UAC,可以在计划任务里创建一个“交互式登录时运行”的任务,用最高权限运行,再在快捷方式里直接指向这个计划任务。这样体验最顺滑,但配置成本稍微高一点。

给同事使用时,我会再顺手做一个“外网模式”的快捷方式,对应internet参数,两个入口清清楚楚。

5.3 切换后的验证,别只 ping 一下

脚本跑完不代表一定成功,验证要分层做。我一般按顺序执行这几条命令:

ipconfig /all route print -4 ping 10.10.20.1 ping 223.5.5.5 nslookup www.example.com

第一次验证是看网卡状态,确认目标网卡已经启用,IP 和网关对不对。第二次是看默认路由,确保0.0.0.0指向我们想要的网关,并且只有一条默认路由。第三次验证网关连通性,第四次验证互联网连通性。最后再用nslookup验证 DNS 解析。如果ping网关通了但nslookup失败,问题多半出在 DNS 上,回到脚本里检查Set-DnsClientServerAddress这段。

如果你在公司内部,内网访问往往不只是通过默认路由,还可能需要访问多个内网网段。这时候就要在脚本里追加静态路由,比如:

route add 172.16.0.0 mask 255.240.0.0 10.10.20.1 metric 20

追加之后,不仅内网网关所在网段可以通,整个 172.16.0.0/12 网段也能通过内网网关访问,不影响默认路由指向互联网。

5.4 切换失败时怎么快速回退

脚本执行到一半报错,最怕的是网卡被禁用后无法恢复。我的经验是准备一个“恢复出厂”小脚本,里面只有两行命令:

netsh interface set interface "以太网" enabled netsh interface set interface "WLAN" enabled

不管当前处于什么状态,先把两块网卡都启用,然后重新进入图形界面检查 IP 和网关,至少能保证设备从一个可操作的状态重新开始。如果是因为手动配置了错误的静态 IP 导致无法上网,可以直接把网卡改成 DHCP 获取,再让它重新拿地址。

另外提醒一句,如果你通过远程桌面或 SSH 连接到那台机器,千万别贸然禁用当前正在使用的网卡,否则远程连接会立刻断开。脚本里加一个确认提示也行,或者明确告诉使用者“切换后远程连接会断一下,需要用另一张网卡的地址重新连接”。

6. 常见问题与排查技巧实录

6.1 问题速查表

把实践中高频出现的问题整理成一张速查表,比抱着文档翻舒服得多。

问题现象常见原因排查与解决办法
提示需要管理员权限脚本没有用管理员身份运行右键脚本,选择“以管理员身份运行”,或检查计划任务最高权限
网卡名称识别不了系统中网卡名不是“以太网”/“WLAN”执行Get-NetAdapter确认实际名称,修改脚本变量
route add 报参数错误网关不可达或缺少 if 参数先确认网关地址,再用route print -4找到接口索引并显式填写
切换后网页打不开默认路由残留或 DNS 配置错误执行route print -4检查默认路由;重新设置 DNS;ipconfig /flushdns
远程连接突然断开脚本禁用了当前正在使用的网卡不要禁用远程会话所在的网卡;改用另一张网卡地址重新连接
PowerShell 提示禁止运行脚本执行策略限制执行Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
杀毒软件拦截 netsh/route安全软件对系统命令敏感添加白名单或改用权限更细分的 PowerShell 命令

6.2 我踩过的几个坑

第一个坑是批处理编码。中文系统下,如果脚本用 UTF-8 保存,运行时的中文提示会出现乱码。解决办法是把文件开头写成chcp 65001 >nul,同时用 UTF-8 编码保存;或者干脆保持系统默认的 GBK 编码,去掉chcp那行。两种方式都能用,最怕的是编码和代码页不匹配。

第二个坑是 DHCP 重新分配路由。有的环境里,无线网卡启用的瞬间会从路由器拿到默认网关,自动生成一条默认路由,即使你后面执行了route delete 0.0.0.0 mask 0.0.0.0,它可能在几秒后又冒出来。应对办法是脚本最后加一次验证,发现多余默认路由再删一次。

第三个坑是网卡名里有空格或者怪异字符,尤其是某些 USB 无线网卡,名字可能叫“Wireless LAN adapter WLAN 2”。在批处理里双引号括起来问题不大,但如果写进 PowerShell 命令里,一定要用变量统一管理,避免手滑打错。

6.3 进一步自动化:检测网络质量以后自动切换

脚本写好了,还可以更进一步。有些人希望“断开无线就自动切有线,有线断了就自动切无线”,这时候单个切换脚本是不够的,需要加一个检测循环。

思路很简单:脚本先 ping 当前主链路的网关,如果连续失败,就自动调用另一个模式的切换函数。在 PowerShell 里可以用一个while循环加Test-Connection实现,但注意不要写得太激进,否则网卡频繁切换反而会影响使用。以我的经验,每 30 秒检测一次,连续失败 3 次再触发切换,体验比较稳定。

这个方案适合对网络可用性要求不高的办公场景,如果业务系统依赖固定 IP 和固定网关,自动切换可能带来更多问题,还是手动点一下更可靠。

最后再分享一个很小的实战习惯:我在脚本开头都会加一句echo 当前时间: %date% %time%,窗口里留下执行痕迹。下次任何人问“你是不是切过网络”,只要把命令行历史或者日志拉出来,一眼就能确认。工具再自动化,也得保留可追踪的记录,这是团队协作里最值钱的一环。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询