能否用CMD/PowerShell/VBS编写ScrollLock切换网卡程序并设为系统服务?
这个方案完全可行,而且能稳定运行,但有几个关键细节需要注意——尤其是当你想把它做成系统服务的时候,Windows服务的会话隔离特性会给键盘状态检测带来一点小麻烦。下面我一步步给你拆解实现思路和注意事项:
1. 核心功能实现脚本
先搞定“检测ScrollLock状态+切换网卡”的核心逻辑,三种脚本都给你准备了示例,记得根据自己的实际网卡名称修改(比如有的网卡叫“本地连接”“以太网2”,先运行对应命令查看准确名称):
PowerShell脚本(推荐,更简洁灵活)
PowerShell对网卡的控制原生支持很好,还能避免重复操作:
# 持续轮询ScrollLock状态(适合任务计划/后台运行) while ($true) { # 获取ScrollLock状态 $scrollLock = [console]::ScrollLock # 匹配以太网和WLAN网卡(根据实际名称调整通配符) $ethernet = Get-NetAdapter -Name "*以太网*" | Select-Object -First 1 $wlan = Get-NetAdapter -Name "*WLAN*" | Select-Object -First 1 if ($scrollLock) { # ScrollLock开启:关闭以太网,开启WLAN(先检查当前状态避免重复操作) if ($ethernet.Status -ne "Disabled") { Disable-NetAdapter -Name $ethernet.Name -Confirm:$false } if ($wlan.Status -ne "Up") { Enable-NetAdapter -Name $wlan.Name -Confirm:$false } } else { # ScrollLock关闭:开启以太网,关闭WLAN if ($ethernet.Status -ne "Up") { Enable-NetAdapter -Name $ethernet.Name -Confirm:$false } if ($wlan.Status -ne "Disabled") { Disable-NetAdapter -Name $wlan.Name -Confirm:$false } } Start-Sleep -Seconds 1 }
先运行
Get-NetAdapter查看你的网卡准确名称,替换掉示例中的通配符。
CMD脚本
用原生CMD命令实现,适合习惯DOS命令的场景:
@echo off :loop :: 检测ScrollLock状态 mode con | findstr /i "ScrollLock.*ON" >nul if %errorlevel% equ 0 ( :: ScrollLock开启:关闭以太网,开启WLAN(替换为你的网卡名称) netsh interface set interface "以太网" disable netsh interface set interface "WLAN" enable ) else ( :: ScrollLock关闭:开启以太网,关闭WLAN netsh interface set interface "以太网" enable netsh interface set interface "WLAN" disable ) timeout /t 1 /nobreak >nul goto loop
先运行
netsh interface show interface查看网卡名称,替换示例中的引号内容。
VBS脚本
用VBS结合WMI控制网卡,调用系统API检测ScrollLock:
Private Declare Function GetKeyState Lib "user32.dll" (ByVal nVirtKey As Long) As Integer Const VK_SCROLL = &H91 Set objWMIService = GetObject("winmgmts:\\.\root\cimv2") Do ' 获取ScrollLock状态 scrollLockOn = (GetKeyState(VK_SCROLL) And &H1) <> 0 ' 匹配网卡(替换为你的网卡名称) Set colNetAdapters = objWMIService.ExecQuery("SELECT * FROM Win32_NetworkAdapter WHERE NetConnectionID IS NOT NULL") For Each objNetAdapter In colNetAdapters If objNetAdapter.NetConnectionID = "以太网" Then Set ethernet = objNetAdapter If objNetAdapter.NetConnectionID = "WLAN" Then Set wlan = objNetAdapter Next ' 切换网卡状态 If scrollLockOn Then ethernet.Disable() wlan.Enable() Else ethernet.Enable() wlan.Disable() End If WScript.Sleep 1000 Loop
2. 做成系统服务的关键坑点
直接把脚本包装成系统服务会遇到一个核心问题:Windows服务默认运行在会话0(非用户交互的后台会话),无法获取当前用户会话的ScrollLock状态——它读到的是后台会话的键盘状态,和你正在使用的会话完全无关。
两种解决方案
方案一:用任务计划代替服务(推荐,简单可靠)
如果不需要“开机即跑、不受用户登录影响”的特性,任务计划是最优解:
- 打开「任务计划程序」,创建基本任务
- 触发器选择「当用户登录时」
- 操作选择「启动程序」,程序填
powershell.exe,参数填-ExecutionPolicy Bypass -File "你的脚本路径\SwitchNetwork.ps1" - 勾选「使用最高权限运行」(切换网卡需要管理员权限)
- 完成后,任务会在你登录时自动启动脚本,持续轮询ScrollLock状态
方案二:强行做成系统服务(需额外配置)
如果一定要做成服务,需要解决会话隔离问题:
- 用第三方工具**NSSM(Non-Sucking Service Manager)**包装脚本(它能让服务运行在用户会话里)
- 下载NSSM后,打开CMD运行
nssm install ScrollLockNetworkSwitch - 在弹出的配置窗口中:
- Path填
powershell.exe - Arguments填
-ExecutionPolicy Bypass -File "你的脚本路径\SwitchNetwork.ps1" - 切换到「登录」标签,选择你的用户账户,输入密码
- 勾选「允许服务与桌面交互」
- Path填
- 启动服务后,它会在你的用户会话里运行,能正确读取ScrollLock状态
注意:这种方式下,当你注销用户后服务会停止,只能在你登录时正常工作。
3. 权限注意事项
不管用哪种方式,切换网卡都需要管理员权限:
- 任务计划必须勾选「使用最高权限运行」
- 手动运行脚本时,右键选择「以管理员身份运行」
- 服务配置时要确保账户有管理员权限
总结
方案完全可行,但直接做系统服务会踩会话隔离的坑,更推荐用任务计划实现,配置简单还能避免不必要的麻烦;如果一定要做成服务,用NSSM包装并配置用户会话运行是可行的。
内容的提问来源于stack exchange,提问作者oliver.bedi

