使用任务计划程序,根据网络环境自动开关代理软件
本文最后更新于 393 天前,其中的信息可能已经有所发展或是发生改变。

住处的路由器经过一番折腾,自带访问国际互联网的环境,而其他地方的网络当然不会有这个东西了,这就需要在电脑上启动代理。每次搬电脑都要开关代理很麻烦,于是心生一计,使用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模式):

Write-Output "Stopping Shadowsocks"
Get-Process | Where-Object {$_.ProcessName.Contains("Shadowsocks") } | Stop-Process
Write-Output "Trying to delete proxy registry"
Remove-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings' -Name "AutoConfigURL"

然后保存。

按上面的步骤创建一个新任务。“触发器”与上面相同。

在“操作”-“程序或脚本”的“添加参数”栏填入刚刚新建的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脚本,少废话,上代码。

Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name ProxyEnable -Value 0 #首先禁用系统代理,防止对检测造成影响
$url = "http://clients3.google.com/generate_204"
$req = [system.Net.WebRequest]::Create($url)
$proxyActive = Get-Process v2rayN -ErrorAction SilentlyContinue #检测v2rayN是否运行,后面那个param是在它没有运行的情况下继续执行脚本
try {
    $res = $req.GetResponse() #获取HTTP状态码
} 
catch [System.Net.WebException] {
    $res = $_.Exception.Response
}
if ($res.StatusCode -eq "NoContent") {
    #能够直连国际互联网
    Write-Output "Google Is Connected, Stopping Proxy"
    Get-Process | Where-Object { $_.ProcessName.Contains("v2ray") } | Stop-Process
}
else {
    #不能直连国际互联网
    if ($null -eq $proxyActive) {
        # 代理未运行,打开代理
        Write-Output "Cannot connect to Google, Starting Proxy"
        &"Your\Path\To\v2rayN.exe"
    }
    else {
        # 代理软件已运行,启用系统代理即可
        Write-Output "Re-enabling Proxy"
        Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name ProxyEnable -Value 1
    }
}    

将里面的 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)

Check if a process is running (microsoft.com)

评论

  1. oh_yes
    1年前
    2021-12-01 16:41:00

    尝试了第一个方法后,发现断开相应的网络也会自动关闭触发时打开的程序,是windows变智能了么?

    • 博主
      oh_yes
      1年前
      2021-12-01 18:24:41

      不知道,我是一次全都设置完了……

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇