<# .SYNOPSIS 通用代理管理脚本 (PowerShell 版) .DESCRIPTION source/加载后使用 proxy 命令管理代理开/关/状态/测试 .NOTES File: proxy.ps1 用法: . .\proxy.ps1 # 加载脚本 proxy on # 开启代理 proxy off # 关闭代理 proxy status # 查看代理状态 proxy test # 测试代理连通性 proxy set [type] # 临时设置代理地址 proxy toggle # 切换开/关 proxy help # 显示帮助 #> # -------------------- 默认配置 -------------------- if (-not $env:_PROXY_HOST) { $env:_PROXY_HOST = "127.0.0.1" } if (-not $env:_PROXY_PORT) { $env:_PROXY_PORT = "7890" } if (-not $env:_PROXY_TYPE) { $env:_PROXY_TYPE = "http" } # http | socks5 | socks4 $global:NO_PROXY_LIST = "localhost,127.0.0.1,::1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16" # -------------------- 辅助:构建代理 URL -------------------- function _BuildProxyUrl { $type = $env:_PROXY_TYPE $host_addr = $env:_PROXY_HOST $port = $env:_PROXY_PORT switch ($type.ToLower()) { "http" { return "http://$host_addr`:$port" } "socks5" { return "socks5://$host_addr`:$port" } "socks4" { return "socks4://$host_addr`:$port" } default { return "$type`://$host_addr`:$port" } } } # -------------------- 辅助:控制台 WinINET 代理 (系统级 IE/Edge) -------------------- function _SetWinInetProxy([string]$proxyUrl) { $regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" if ($proxyUrl) { Set-ItemProperty -Path $regPath -Name ProxyEnable -Value 1 Set-ItemProperty -Path $regPath -Name ProxyServer -Value ($proxyUrl -replace '^\w+://', '') Set-ItemProperty -Path $regPath -Name ProxyOverride -Value $global:NO_PROXY_LIST } else { Set-ItemProperty -Path $regPath -Name ProxyEnable -Value 0 } # 广播 WM_SETTINGCHANGE,让其他程序感知代理变更 $sig = @' [DllImport("wininet.dll", SetLastError=true)] public static extern bool InternetSetOption(IntPtr hInternet, int dwOption, IntPtr lpBuffer, int dwBufferLength); [DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)] public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam, uint fuFlags, uint uTimeout, out UIntPtr lpdwResult); '@ try { Add-Type -MemberDefinition $sig -Namespace WinAPI -Name ProxyHelper -ErrorAction SilentlyContinue [WinAPI.ProxyHelper]::InternetSetOption([IntPtr]::Zero, 39, [IntPtr]::Zero, 0) | Out-Null # PROXY_SETTINGS_CHANGED $HWND_BROADCAST = [IntPtr]0xffff $WM_SETTINGCHANGE = 0x1A $result = [UIntPtr]::Zero [WinAPI.ProxyHelper]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [UIntPtr]::Zero, "Environment", 2, 2000, [ref]$result) | Out-Null } catch {} } # ==================================================================== # 开启代理 # ==================================================================== function Proxy-On { $url = _BuildProxyUrl # --- 进程级环境变量 --- $env:http_proxy = $url $env:HTTP_PROXY = $url $env:https_proxy = $url $env:HTTPS_PROXY = $url $env:all_proxy = $url $env:ALL_PROXY = $url $env:no_proxy = $global:NO_PROXY_LIST $env:NO_PROXY = $global:NO_PROXY_LIST $env:ftp_proxy = $url $env:FTP_PROXY = $url $env:rsync_proxy = $url # --- 用户级环境变量(持久化,新开终端也生效)--- [Environment]::SetEnvironmentVariable("http_proxy", $url, "User") [Environment]::SetEnvironmentVariable("https_proxy", $url, "User") [Environment]::SetEnvironmentVariable("all_proxy", $url, "User") [Environment]::SetEnvironmentVariable("no_proxy", $global:NO_PROXY_LIST, "User") # --- Git --- git config --global http.proxy $url 2>$null git config --global https.proxy $url 2>$null # --- NPM --- npm config set proxy $url 2>$null npm config set https-proxy $url 2>$null # --- Yarn --- yarn config set proxy $url 2>$null yarn config set https-proxy $url 2>$null # --- Windows 系统 WinINET (IE/Edge/Chrome 等) --- _SetWinInetProxy $url Write-Host "[✓] 代理已开启 → " -ForegroundColor Green -NoNewline Write-Host $url -ForegroundColor White Write-Host " NO_PROXY → " -ForegroundColor Green -NoNewline Write-Host $global:NO_PROXY_LIST -ForegroundColor White } # ==================================================================== # 关闭代理 # ==================================================================== function Proxy-Off { # --- 进程级环境变量 --- $vars = @("http_proxy","HTTP_PROXY","https_proxy","HTTPS_PROXY","all_proxy","ALL_PROXY", "no_proxy","NO_PROXY","ftp_proxy","FTP_PROXY","rsync_proxy") foreach ($v in $vars) { Remove-Item -Path "Env:$v" -ErrorAction SilentlyContinue } # --- 用户级环境变量 --- foreach ($v in @("http_proxy","https_proxy","all_proxy","no_proxy")) { [Environment]::SetEnvironmentVariable($v, $null, "User") } # --- Git --- git config --global --unset http.proxy 2>$null git config --global --unset https.proxy 2>$null # --- NPM --- npm config delete proxy 2>$null npm config delete https-proxy 2>$null # --- Yarn --- yarn config delete proxy 2>$null yarn config delete https-proxy 2>$null # --- Windows 系统 WinINET --- _SetWinInetProxy $null Write-Host "[✓] 代理已关闭" -ForegroundColor Red } # ==================================================================== # 查看代理状态 # ==================================================================== function Proxy-Status { Write-Host "" Write-Host "========== 代理状态 ==========" -ForegroundColor White # 环境变量 Write-Host "`n[环境变量]" -ForegroundColor White $envVars = @("http_proxy", "https_proxy", "all_proxy", "no_proxy", "ftp_proxy") foreach ($v in $envVars) { $val = [Environment]::GetEnvironmentVariable($v, "Process") if ($val) { Write-Host (" {0,-14} → {1}" -f $v, $val) -ForegroundColor Green } else { Write-Host (" {0,-14} → (未设置)" -f $v) -ForegroundColor DarkGray } } # 用户级环境变量 Write-Host "`n[用户级环境变量 (持久化)]" -ForegroundColor White foreach ($v in @("http_proxy", "https_proxy", "all_proxy", "no_proxy")) { $val = [Environment]::GetEnvironmentVariable($v, "User") if ($val) { Write-Host (" {0,-14} → {1}" -f $v, $val) -ForegroundColor Green } else { Write-Host (" {0,-14} → (未设置)" -f $v) -ForegroundColor DarkGray } } # Git Write-Host "`n[Git 配置] (global)" -ForegroundColor White $gitHttp = git config --global --get http.proxy 2>$null $gitHttps = git config --global --get https.proxy 2>$null if ($gitHttp -or $gitHttps) { if ($gitHttp) { Write-Host " http.proxy → $gitHttp" -ForegroundColor Green } if ($gitHttps) { Write-Host " https.proxy → $gitHttps" -ForegroundColor Green } } else { Write-Host " (未配置)" -ForegroundColor DarkGray } # NPM if (Get-Command npm -ErrorAction SilentlyContinue) { Write-Host "`n[NPM 配置]" -ForegroundColor White $npmProxy = npm config get proxy 2>$null $npmHttps = npm config get https-proxy 2>$null if ($npmProxy -and $npmProxy -ne "null" -and $npmProxy -ne "undefined") { Write-Host " proxy → $npmProxy" -ForegroundColor Green } else { Write-Host " proxy → (未设置)" -ForegroundColor DarkGray } if ($npmHttps -and $npmHttps -ne "null" -and $npmHttps -ne "undefined") { Write-Host " https-proxy → $npmHttps" -ForegroundColor Green } else { Write-Host " https-proxy → (未设置)" -ForegroundColor DarkGray } } # Windows 系统代理 Write-Host "`n[Windows 系统 WinINET 代理]" -ForegroundColor White $regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings" if (Test-Path $regPath) { $enabled = (Get-ItemProperty -Path $regPath -Name ProxyEnable -ErrorAction SilentlyContinue).ProxyEnable $server = (Get-ItemProperty -Path $regPath -Name ProxyServer -ErrorAction SilentlyContinue).ProxyServer if ($enabled -eq 1) { Write-Host " ProxyEnable → 1" -ForegroundColor Green Write-Host " ProxyServer → $server" -ForegroundColor Green } else { Write-Host " ProxyEnable → 0 (已禁用)" -ForegroundColor DarkGray } } else { Write-Host " (无法读取注册表)" -ForegroundColor DarkGray } Write-Host "" } # ==================================================================== # 测试代理连通性 # ==================================================================== function Proxy-Test { $url = _BuildProxyUrl Write-Host "[测试代理] $url`n" -ForegroundColor White # Google (通过代理) Write-Host " Google (proxy) → " -NoNewline try { $r = Invoke-WebRequest -Uri "https://www.google.com" -Proxy $url -TimeoutSec 5 -UseBasicParsing -ErrorAction Stop if ($r.StatusCode -in 200,301,302) { Write-Host "✓ OK ($($r.StatusCode))" -ForegroundColor Green } else { Write-Host "✗ FAIL ($($r.StatusCode))" -ForegroundColor Red } } catch { Write-Host "✗ FAIL" -ForegroundColor Red } # GitHub (通过代理) Write-Host " GitHub (proxy) → " -NoNewline try { $r = Invoke-WebRequest -Uri "https://github.com" -Proxy $url -TimeoutSec 5 -UseBasicParsing -ErrorAction Stop if ($r.StatusCode -in 200,301,302) { Write-Host "✓ OK ($($r.StatusCode))" -ForegroundColor Green } else { Write-Host "✗ FAIL ($($r.StatusCode))" -ForegroundColor Red } } catch { Write-Host "✗ FAIL" -ForegroundColor Red } # 本地直连 (不走代理) Write-Host " Baidu (direct) → " -NoNewline try { $r = Invoke-WebRequest -Uri "https://www.baidu.com" -TimeoutSec 3 -UseBasicParsing -NoProxy -ErrorAction Stop if ($r.StatusCode -in 200,301,302) { Write-Host "✓ OK ($($r.StatusCode))" -ForegroundColor Green } else { Write-Host "✗ FAIL ($($r.StatusCode))" -ForegroundColor Red } } catch { # PowerShell 5.1 不支持 -NoProxy,退而用 curl try { $code = (curl.exe -s -o NUL -w "%{http_code}" --max-time 3 --noproxy "*" https://www.baidu.com 2>$null) if ($code -match "200|301|302") { Write-Host "✓ OK ($code)" -ForegroundColor Green } else { Write-Host "✗ FAIL" -ForegroundColor Red } } catch { Write-Host "✗ FAIL" -ForegroundColor Red } } Write-Host "" } # ==================================================================== # 临时设置代理地址 # ==================================================================== function Proxy-Set { param( [Parameter(Position=0)][string]$ProxyHost, [Parameter(Position=1)][string]$ProxyPort, [Parameter(Position=2)][string]$ProxyType = "http" ) if (-not $ProxyHost -or -not $ProxyPort) { Write-Host "用法: proxy set [http|socks5]" -ForegroundColor Yellow Write-Host '示例: proxy set 192.168.1.100 1080 socks5' -ForegroundColor Yellow return } $env:_PROXY_HOST = $ProxyHost $env:_PROXY_PORT = $ProxyPort $env:_PROXY_TYPE = $ProxyType Write-Host "[✓] 代理地址已设置为 ${ProxyType}://${ProxyHost}:${ProxyPort}" -ForegroundColor Green Write-Host " 执行 'proxy on' 启用新的代理地址" -ForegroundColor Green } # ==================================================================== # 主入口:proxy 命令 # ==================================================================== function proxy { param( [Parameter(Position=0)][string]$Action = "help", [Parameter(Position=1, ValueFromRemainingArguments)][string[]]$Args ) switch ($Action.ToLower()) { "on" { Proxy-On } "off" { Proxy-Off } "status" { Proxy-Status } "test" { Proxy-Test } "toggle" { if ($env:http_proxy) { Proxy-Off } else { Proxy-On } } "set" { if ($Args -and $Args.Count -ge 2) { $type = if ($Args.Count -ge 3) { $Args[2] } else { "http" } Proxy-Set -ProxyHost $Args[0] -ProxyPort $Args[1] -ProxyType $type } else { Proxy-Set } } "help" { Write-Host @" ========== proxy.ps1 — 通用代理管理 ========== 用法: . .\proxy.ps1 # 加载脚本(Dot-Source) proxy on # 开启代理 (环境变量 + 系统WinINET + git + npm) proxy off # 关闭代理 proxy status # 查看代理状态 proxy test # 测试代理连通性 proxy toggle # 切换开/关 proxy set [type]# 设置代理地址 proxy help # 显示帮助 默认配置 (可通过环境变量覆盖): _PROXY_HOST = $($env:_PROXY_HOST) _PROXY_PORT = $($env:_PROXY_PORT) _PROXY_TYPE = $($env:_PROXY_TYPE) (http | socks5 | socks4) 自定义示例: `$env:_PROXY_HOST = "10.0.0.5" # 修改主机 `$env:_PROXY_PORT = "1080" # 修改端口 proxy on # 启用 "@ -ForegroundColor Cyan } default { Write-Host "未知命令: $Action (使用 'proxy help' 查看帮助)" -ForegroundColor Red } } } # -------------------- 加载提示 -------------------- if ($MyInvocation.Line -notmatch '\$\s*\(?\s*\.\s+.*proxy\.ps1') { # 被直接执行而非 dot-source 时 if ($args.Count -eq 0) { # 无参数直接执行,先 dot-source 自己 Write-Host "[proxy.ps1] 请使用 '. .\proxy.ps1' 来加载脚本。" -ForegroundColor Yellow Write-Host "[proxy.ps1] 如果要直接执行命令, 请运行: .\proxy.ps1 on" -ForegroundColor Yellow } } else { Write-Host "[proxy.ps1] 已加载。使用 'proxy help' 查看用法。" -ForegroundColor Cyan }