住处的路由器经过一番折腾,自带访问国际互联网的环境,而其他地方的网络当然不会有这个东西了,这就需要在电脑上启动代理。每次搬电脑都要开关代理很麻烦,于是心生一计,使用 Windows 自带的十分完善的任务计划功能,来实现根据网络环境的代理软件自动开关功能。理论上这同时适用于 Clash、ShadowsocksR 等代理软件。
在 Windows 11 build 22000.282 测试通过,理论上近几个大版本的 Windows 10 也同样适用。
自动打开代理软件
这一部分讲述了在连接到某一特定 SSID 的 WiFi 网络时如何启动代理,以 Shadowsocks 为例。
使用 Windows 搜索 “计划任务” 或者 “taskschd” 可以找到任务计划程序。
点击右侧 “创建任务”,随便起个名字。
切换到 “触发器” 选项卡,新建 “发生事件时” 触发器,“开始任务”选择 “发生事件时”,“日志” 选择 “Microsoft-Windows-NetworkProfile/Operational”,“源” 选择 “NetworkProfile”,“事件 ID” 填写“10000”,其他不变,如图。
切换到 “操作” 选项卡,新建操作,在 “程序或脚本” 栏里浏览并选择你的 Shadowsocks 主程序,其他不变,点击确定。
再切换到 “条件” 选项卡,选中 “只有在以下网络连接可用时才启动”,选择你希望打开 Shadowsocks 的网络环境。某些时候,网络 SSID 并不等于环境名称,这时最好查看“找到真正的网络名称” 部分以确保选择正确。这样相当于监听每一次网络环境改变事件,再检查当前网络环境,如果符合条件则启动。同时还需要关闭”只有在计算机使用交流电源时才启动此任务“,毕竟能拿着电脑到处跑的人应该会经常用电池吧。
点击确定,即可完成设置。
找到真正的网络名称
有些时候,你可能会遇到和我一样的情况:明明想找一个名为 xxx 的 WiFi,但在 “只有在以下网络连接可用时才启动” 下拉框中却发现了形如 “xxx 1”“xxx 2” 之类的网络。如果没有这种情况,那很好,你不用看这一小节了;否则,需要打开 “适配器选项” 窗口来确定真正的网络名称。
这里吐槽一下小米互传:就不能固定一个 SSID 吗?
首先要连接目标网络,然后根据操作系统不同,有不同的步骤。
对于 Windows 10,在任务栏网络图标右键,选择 “打开网络和 Internet 设置”,然后点击 “更改适配器选项”;而对 Windows 11,要打开设置 - 网络 & Internet - 高级网络设置 - 更多网络适配器选项。会弹出如下图的窗口。
这里再骂一次微软,Windows 10 适配器选项页面的高分屏优化都比 11 好,起码字体没毛边。
这里根据你的情况寻找你的网络名称,比如我的是 “PDCN_5G 7”。
自动关闭代理软件
仍然以 Shadowsocks 为例。这个实现起来相对麻烦些,因为任务计划没有设定关闭程序的操作。好在我们有 PowerShell,所以我们可以使用 PoweShell 脚本来结束进程。
新建一个文本文档,将扩展名改为. ps1,文件名任取。然后,在里面粘贴以下内容(假设你的 Shadowsocks 设定的是 PAC 模式):
|
|
然后保存。
按上面的步骤创建一个新任务。“触发器” 与上面相同。
在 “操作”-“程序或脚本” 的“添加参数”栏填入刚刚新建的 PowerShell 脚本路径,“程序或脚本”填入“pwsh.exe”(如果你安装了新版 PowerShell Core)或“powershell.exe”(通用,但是是老版本),其他不变,确定。如下图:
编辑执行脚本操作
“条件”-“只有在以下网络连接可用时” 改为你希望自动关闭 Shadowsocks 的网络环境。
点击确定,即可完成设置。不想了解细节的读者,不需要读本节中下面的部分。
我们都知道,要关闭 Shadowsocks,当然要结束 Shadowsocks.exe。它运行的时候,还会同时启动 Privoxy 透明代理,但结束主程序的时候它也会一起关闭,所以没有必要考虑这个。
如果你使用的是 PAC 代理模式而不是全局代理,有时系统设置 - 网络 & Internet - 代理 - 使用设置脚本的开关并不会关闭,部分影响网络浏览。这个开关由注册表键值 HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\AutoConfigURL 所管理,如果存在则代表这个开关打开,并将 PAC 代理指向它的值,键值字符串代表设置的代理服务器地址。那么,我们增加一条命令将这个键删掉,就可以保证彻底关闭了。
进阶:自动检测网络环境,开关代理
这部分以 v2rayN 为例。如果你经常在多个网络环境之间穿梭,每个网络条件不同(甚至同一个网络路由器端的梯子都有可能挂掉),上面的那个办法就不是那么好用了。既然我们写了 PowerShell 脚本,不妨一步到位,直接检测网络环境。
首先你需要新建一个在网络环境改变的时候就调用的任务计划,而不需要特定网络连接条件,可以参照本文的 “自动打开代理” 部分。
然后新建一个 PowerShell 脚本,少废话,上代码。
|
|
将里面的 Your\Path\To\v2rayN.exe
替换为 v2rayN.exe 路径,然后让那个任务计划在满足条件时执行它。
v2rayN 采用的是系统代理方案,把 v2rayN.exe 结束掉,会自动结束 xray.exe,但要手动控制系统代理。控制它的注册表项是 HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ProxyEnable,类型为 DWORD,1 为开启,0 为关闭。
显而易见,http://clients3.google.com/generate_204 是在墙外的网站。如果访问正常,这个页面会返回一个 HTTP 204 NoContent,否则 res 会是 $null。
参考文献
windows - How to launch a command on network connection/disconnection? - Super User
利用 Windows 计划任务定时关闭程序 - 蜂鸣器 (fmqcloud.com)
一键打开关闭 ie 代理 - 问题求助 - 小众软件官方论坛 (appinn.net)
How to Get, Edit, Create and Delete Registry Keys with PowerShell (netwrix.com)
如何在 powershell 中让运行的程序停止 _百度知道 (baidu.com)
设定 Windows 计划任务定期执行 PowerShell 脚本【图文】_StanlyCheng_51CTO 博客
如何在 PowerShell 中获取数字 HTTP 状态码? - 问答 - 云 + 社区 - 腾讯云 (tencent.com)