太长不看版
下载即可使用,包含 AutoProxy.exe 和 Config.yaml,在 Config.yaml 中进行配置后双击运行 exe 文件即可开启/关闭代理,可以通过下面的 .py 源码自行构建 exe 程序。
下载地址:Gloxina Cloud
注意事项
下面的脚本/软件全部涉及到 Windows 注册表的修改,如果你需要对其进行修改,请确保你具有相关的背景知识!万分小心!
下面的所有方案仅在 Windows 10/11 上成功运行,不保证 Windows 10 以下的版本能够顺利运行。
下面的 Bat 和 PowerShell 都会存在 UTF-8 显示中文时乱码的问题,可以通过更换到 GBK 或 ANSI 编码来解决此问题。
理论
由于本人比较懒,不想每次都跑到设置里来开启/关闭 Windows 的代理,于是写了个脚本并且固定快捷方式到任务栏,就可以进行快速操作了。
众所周知,Windows 的很多设置都对应着一堆注册表值,包括代理设置。
代理设置的注册表:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings
- ProxyEnable:
对应代理的开关,1为开启0为关闭。 - ProxyServer:
对应代理服务器的地址,格式为 “address:port”,例如 “127.0.0.1:443” 或者 “example.com:80″。当地址为域名时,Windows 会自动在前面加上 http://。 - ProxyOverride:
对应“请勿对以下列条目开头的地址使用代理服务器。若有多个条目,请使用英文分号 (;) 来分隔”以及“请勿将代理服务器用于本地(Intranet)地址”。如果注册表里没有这一项也正常,因为这两玩意没填的时候 Windows 是不会创建这个注册表项的。另外,“请勿将代理服务器用于本地(Intranet)地址”并不是靠单独的键值来进行开关的。如果开启的话,Windows 会在 ProxyOverride 一栏中添加 “<local>” 这一值。如果填写了“请勿对以下列条目开头的…“这一栏的话,则会将 “<local>” 这一值放在最后面,例如:
192.168.1.*;10.0.*.*;<local>
然后,再通过一个外部配置文件(Config.yaml或者其他啥玩意)并且给这个配置文件创建一个桌面快捷方式,就可以快速编辑代理地址了。另外,再添加一个代理开启或者关闭的通知,完美。
通过批处理脚本(Bat)实现
Bat 脚本使用 Windows 祖传的 msg.exe 来实现,弹窗有点古老。如果想要比较*城市化*的通知,可以参考下面的 PowerShell 的 ps1 脚本,通过 Module 可以实现弹出式通知,就是右下角弹出的那个通知。当然那玩意只能在 Windows 10/11 上使用,Bat 则*比较*通用。
setlocal
::设置成临时变量环境
for /f "usebackq delims=" %%a in ("Config.txt") do set ADDRESS=%%a
::读取 Config.txt 里的内容,并且写成变量
for /f "tokens=1,2,* " %%i in ('REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable ^| find /i "ProxyEnable"') do (set /A ProxyEnableValue=%%k)
::读取注册表,确定代理的状态
if %ProxyEnableValue% equ 0 (
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable /t REG_DWORD /d 1 /f >nul 2>nul
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer /d "%ADDRESS%" /f >nul 2>nul
msg * /time:5 "代理已开启"
) else if %ProxyEnableValue% equ 1 (
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyEnable /t REG_DWORD /d 0 /f >nul 2>nul
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings" /v ProxyServer /d "" /f >nul 2>nul
msg * /time:5 "代理已关闭"
)
endlocal
::退出临时变量环境
如上,这玩意需要在 Bat 脚本的同级目录下手动建一个 Config.txt,然后脚本会读取这个文本文档里的内容,具体格式为 “address:port”,例如 “127.0.0.1:443” 或者 “example.com:80”(没错就和上面一样)。这个脚本没有实现 “ProxyOverride” 的功能,因为我改用 Python 了🫠
通过 Windows Powershell 实现
OK现在来到了城市化环节,由于 Powershell 的尿性,默认这玩意是不允许运行第三方脚本的,需要手动开启一下,方法可以在 cn.bing.com 上找到(主要是我忘记是哪一条了🫠可以在运行 ps1 脚本的时候看看出现的错误,然后根据错误查一下解决方法。或者可以使用下面的 VBS 脚本来启动,就可以直接运行了)另外,这个脚本引用了 BurntToast 模块来进行通知,所以要先安装这个模块(当然,如果不需要通知的话,在脚本里删掉相关内容就行)在 PowerShell 中运行以下指令安装 BurntToast 模块:
Install-Module -Name BurntToast
安装之后就可以写脚本了,创建一个 xxx.ps1 ,写入以下内容:
# 引用模组 BurntToast
# 用法:New-BurntToastNotification -AppLogo "Logo图片路径" -Text "标题", "正文"
Import-Module BurntToast
# 定义配置文件的路径,顺便给配置文件内容设个变量
$FilePath = ".\Config.yml"
$Config = Get-Content -Path $FilePath
# 给下面会用到的几个变量先定义空值,防止因为找不到某个变量导致脚本运行到一半然后当场暴毙
$ProxyServer = ""
$ProxyOverride = ""
$NoticeImage = ""
foreach ($line in $Config)
{
$line = $line.Trim()
if ($line -like "#*" -or [string]::IsNullOrWhiteSpace($line))
{
continue
}
if ($line -like "ProxyServer: *")
{
$ProxyServer = $line -replace "ProxyServer: *", ""
$ProxyServer = $ProxyServer.Trim('"')
}
elseif ($line -like "ProxyOverride: *")
{
$ProxyOverride = $line -replace "ProxyOverride: *", ""
$ProxyOverride = $ProxyOverride.Trim('"')
}
elseif ($line -like "NoticeImage: *")
{
$NoticeImage = $line -replace "NoticeImage: *", ""
$NoticeImage = $NoticeImage.Trim('"')
}
}
# 从注册表里读取代理服务器的状态
$ProxyStatus = Get-ItemPropertyValue -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name ProxyEnable
# 根据从注册表里读取到的代理状态来进行配置,如果是0,就开启代理;如果是1,就关闭代理
if ($ProxyStatus -eq 0)
{
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name ProxyEnable -Value 1
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name ProxyServer -Value $ProxyServer
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name ProxyOverride -Value "$ProxyOverride"
New-BurntToastNotification -AppLogo "$NoticeImage" -Text "Windows 网络代理", "状态:已开启", "地址:$ProxyServer"
}
elseif ($ProxyStatus -eq 1)
{
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name ProxyEnable -Value 0
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name ProxyServer -Value ""
Set-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" -Name ProxyOverride -Value ""
New-BurntToastNotification -AppLogo "$NoticeImage" -Text "Windows 网络代理", "状态:已关闭"
}
接下来在同级目录下创建一个 Config.yml(注意大小写)(本来想在 PowerShell 里面使用 yaml 解释器模块的,但是考虑到这样又要安装新的模块就放弃了,改用读取到#和空行就跳过该行,然后匹配关键字的方式来提取内容并且转换成变量。所以最好不要在配置文件里添加新的内容,防止出现什么奇怪的问题),并且写入以下内容:
# 代理服务器地址
ProxyServer: "127.0.0.1:443"
# 不代理下列条目开头的地址,有多个项目则使用英文分号进行分隔
#例如:localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*;<local>
ProxyOverride: "<local>"
# 弹出通知的图片路径,最好是同级,例如.\Image.png
# 如果不指定的话就设置为空,即NoticeImage: "",不要删除下面这一条目,否则可能出现奇怪的问题
NoticeImage: ".\Image.png"
这样就完成了本体。然而,由于 PowerShell 的尿性,ps1的默认打开方式是记事本或者 IDE,所以可以手动把打开方式设置为 PowerShell,或者创建一个 VBS 脚本来启动(这里推荐创建 VBS 脚本,注意要和 ps1 脚本同级),在 xxx.vbs 中写入以下内容:
Dim shell
Set shell = CreateObject("WScript.Shell")
shell.Run "cmd.exe /c powershell -ExecutionPolicy Bypass -File "".\xxx.ps1""", 0, True
Set shell = Nothing
现在就可以通过创建的 VBS 脚本来运行 ps1 脚本,然后配置代理了。可以在桌面创建快捷方式或者固定到任务栏,方便快速切换。
通过 Python 实现(推荐)
虽然通过 Python 脚本实现需要 Python 环境,但是 Python 脚本可以打包成 exe 文件,打包后只有两个文件,AutoProxy.exe和Config.yaml,下载就可以直接使用:Gloxina Cloud
由于包含了 Yaml 解释器和 Plyer 通知模块,这玩意的体积高达 7.73 MB 🫠但是比 PowerShell 和 Bat 都简洁那么一点点。下面是原始的 Python 代码:
# coding=utf-8
import os
import yaml
import winreg as reg
from plyer import notification
import threading
def show_notification(title, message):
notification.notify(
title=title,
message=message,
timeout=10
)
file_path = r"./Config.yaml"
with open(file_path, 'r', encoding='utf-8') as file:
config = yaml.safe_load(file)
proxy_server = config.get("ProxyServer", "").strip('"')
proxy_override = config.get("ProxyOverride", "").strip('"')
key_path = r"Software\Microsoft\Windows\CurrentVersion\Internet Settings"
with reg.OpenKey(reg.HKEY_CURRENT_USER, key_path) as key:
proxy_status, _ = reg.QueryValueEx(key, "ProxyEnable")
if proxy_status == 0:
with reg.OpenKey(reg.HKEY_CURRENT_USER, key_path, 0, reg.KEY_SET_VALUE) as key:
reg.SetValueEx(key, "ProxyEnable", 0, reg.REG_DWORD, 1)
reg.SetValueEx(key, "ProxyServer", 0, reg.REG_SZ, proxy_server)
reg.SetValueEx(key, "ProxyOverride", 0, reg.REG_SZ, proxy_override)
threading.Thread(target=show_notification, args=("Windows 网络代理", f"状态:已启动\n地址:{proxy_server}")).start()
elif proxy_status == 1:
with reg.OpenKey(reg.HKEY_CURRENT_USER, key_path, 0, reg.KEY_SET_VALUE) as key:
reg.SetValueEx(key, "ProxyEnable", 0, reg.REG_DWORD, 0)
reg.SetValueEx(key, "ProxyServer", 0, reg.REG_SZ, "")
reg.SetValueEx(key, "ProxyOverride", 0, reg.REG_SZ, "")
threading.Thread(target=show_notification, args=("Windows 网络代理", "状态:已关闭")).start()
Config.yaml 中的内容:
# 代理服务器地址
ProxyServer: "127.0.0.1:443"
# 不代理下列条目开头的地址,有多个项目则使用英文分号进行分隔
# localhost;127.*;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*
ProxyOverride: "<local>"
总结
推荐使用 Python 方案。如果需要使用 Bat 或者 PowerShell 方案,可能会存在编码问题,如果使用 UTF-8 编码保存并运行的话,大概率会出现中文显示异常的问题。这时候可以通过转换成 ANSI 或者 GBK 编码来解决此问题(脚本和配置文件都要改,使用相同的编码)
发表回复