那我还是多问下,如果任务之间没有强关联,谁第一第二启动又有什么区别呢,最终结果都是启动,且互不影响。
有关联!具体需求是应该先clash后启动别的东西,不然某些软件没有代理会报错啥的,需要刷新,有时候懒得刷新。
嗯,对于很多场景来说延迟
启动是一种看起来可靠的解决方案,但是个人认为,延迟
启动并不能算得上顺序
,因为循序的含义就是行为结果有先后,而延迟
只是定义了启动的先后,很多场景下,也会出现第一个程序并没有达到预期结果,即使延迟了,第二个程序还是启动快了的情况。
针对延迟启动和程序启动顺序两个概念的个人观点
好比我们在开发的时候我们找不到这个生命周期的API,然后使用CPU定时一个magic的延迟,最终达到功能效果:
// 伪代码
const A = new A_Process()
const B = new B_Process()
// 系统启动完后
System.onStarted(()=>{
// 原来应该使用的API
System.onADidWork(()=>{
B.start();
})
A.start(); // 程序A一般情况下只要运行5秒钟就可以达到work效果
// 而有时候我们偷懒,因为onADidWork这个API太难实现了
// 于是我们就
setTimeout(()=>{
B.start();
// 特意延迟了10秒,肯定够了吧我的天。
}, 10 * 1000)
})
System.start();
可以看到伪代码里面,为了严谨的顺序
,其实是要去定义实现onADidWork
这个API的,以告诉需要的人,A已经达到预设的状态了,这个状态也是我上面所说的健康
。只是大部分情况下,我们简单setTimeout,就是说延迟
启动,其实已经很可靠。
针对佬友的具体需求我们来通过AI简单做一个严谨的启动脚本
虽然延迟启动
已经满足了,但是严谨的佬友还是会觉得,要是clash哪天抽风了,虽然启动了,但是愣是没有开启系统代理
咋办(比如:修改系统代理的权限被关掉了,程序没修改成功,又比如clash虽然启动了,但是CPU就是没排到队,愣是等到了其他软件都已经开启了,clash才启动到成功修改系统代理)
- 需求分析,需要实现的关键:
- clash启动,并且系统有可用的代理
- 再能够自定义启动其他程序
- 技术选型,使用场景就是很正常的电脑,最好是不要安装什么依赖:
- powershell脚本就决定是它了
- 功能设计:
- 考虑到关键的条件其实之和clash有关,那clash直接由系统定义自启动,脚本就只检查是否有代理生效,不去入侵clash如何自启动了
- 脚本应该支持全局变量设定一个等待代理生效的最大尝试次数或者总等待时间,超时后仍然启动后续程序,没有交互的情况下就这样办吧
- 后续程序应该提供一个方便用户修改的列表,用户只需要修改这个列表定义,就可以实现clash工作后有什么软件需要启动
- 检测代理是否生效,那就调用windows的
curl
或者invoke-webrequest
,很幸运,在windows上,这两个exe都是默认会使用系统代理的,访问https://www.google.com,如果不超时那么就是已经可以了。 - 这个脚本应该会以windows的
计划任务
中的开启启动来运行,所以最好搞一个固定的日志文件方便debug。
把以上内容全部输入google-gemini-2.5-pro-exp-03-25
,得出的成品:
<#
如何使用:
1. 修改 $targetUrl 为一个可靠的、通常需要代理才能访问或稳定访问的地址。
2. 修改 $requestTimeoutSeconds 来设置每次网络请求的超时时间。
3. 修改 $maxAttempts 和 $retryIntervalSeconds 来控制检查代理的总时长和频率。
4. 在 $appsToStart 数组中填入你需要在此脚本成功检测到代理后启动的应用程序的完整路径(可以是 .exe, .com, .bat, .lnk 等)。
5. 保存脚本为 .ps1 文件。
6. 在 PowerShell 中运行此脚本 (.\StartAppsAfterProxy.ps1)。
注意:你可能需要调整 PowerShell 执行策略才能运行脚本 (例如, 以管理员身份运行 PowerShell 并执行 Set-ExecutionPolicy RemoteSigned)。
#>
#region 配置区域 - 请根据需要修改以下变量
# 用于测试代理连接的目标 URL
$targetUrl = "https://www.google.com"
# $targetUrl = "https://api.ipify.org" # 备选:一个简单的返回 IP 的 API
# 每次 Web 请求的超时时间(秒)
$requestTimeoutSeconds = 5
# 检测代理状态的最大尝试次数
$maxAttempts = 12 # 例如,12 次 * 5 秒间隔 = 最多等待 60 秒
# 每次尝试之间的间隔时间(秒)
$retryIntervalSeconds = 5
# 代理生效后需要启动的应用程序列表
# 请使用完整路径,可以是可执行文件 (.exe) 或快捷方式 (.lnk)
$appsToStart = @(
"C:\Program Files\Google\Chrome\Application\chrome.exe",
"C:\Users\YourUsername\AppData\Local\Discord\Update.exe --processStart Discord.exe", # 示例:带参数启动
"C:\Path\To\Your\Shortcut.lnk"
# 在这里添加更多应用程序的路径...
# "C:\Program Files\Mozilla Firefox\firefox.exe"
)
# 日志文件路径
$logFilePath = "$env:USERPROFILE\Desktop\proxy_check_log.txt
#endregion 配置区域
#region 函数定义
function Test-ProxyConnection {
param(
[string]$Url,
[int]$Timeout
)
Write-Host "正在尝试访问 $Url (超时时间: ${Timeout}s)..."
try {
# -UseBasicParsing 避免下载和解析内容,仅检查连接性,速度更快
# -ErrorAction Stop 确保任何错误(包括超时)都会被 catch 捕获
Invoke-WebRequest -Uri $Url -UseBasicParsing -TimeoutSec $Timeout -ErrorAction Stop
# 如果上面命令成功执行没有抛出异常,则认为代理连接成功
Write-Host "访问成功!代理似乎已生效。" -ForegroundColor Green
return $true
} catch {
# 捕获所有类型的错误(网络问题、超时、DNS问题等)
Write-Warning "代理检测失败: $($_.Exception.Message)"
return $false
}
}
#endregion 函数定义
#region 日志记录设置
# 开始记录日志
if (Test-Path $logFilePath) {
Remove-Item $logFilePath -Force # 如果日志文件已存在,先删除
}
Start-Transcript -Path $logFilePath -Append -ErrorAction Stop
#endregion 日志记录设置
#region 主逻辑
Write-Host "--- 启动应用程序前的代理检测脚本 ---"
Write-Host "将尝试最多 $maxAttempts 次检测代理状态,每次间隔 $retryIntervalSeconds 秒。"
$proxyReady = $false
for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
Write-Host "`n[尝试 $attempt / $maxAttempts]"
if (Test-ProxyConnection -Url $targetUrl -Timeout $requestTimeoutSeconds) {
$proxyReady = $true
break # 代理已就绪,跳出循环
}
if ($attempt -lt $maxAttempts) {
Write-Host "将在 $retryIntervalSeconds 秒后重试..."
Start-Sleep -Seconds $retryIntervalSeconds
} else {
Write-Warning "`n已达到最大尝试次数 ($maxAttempts),代理仍未按预期工作。"
}
}
# 无论代理是否就绪,都尝试启动应用程序(根据之前的讨论)
Write-Host "`n--- 代理检测阶段结束 ---"
if ($proxyReady) {
Write-Host "代理已确认可用,正在启动指定的应用程序..." -ForegroundColor Cyan
} else {
Write-Warning "未在指定时间内确认代理可用,但仍将尝试启动指定的应用程序..."
}
if ($appsToStart.Count -eq 0) {
Write-Host "没有配置需要启动的应用程序。"
} else {
foreach ($appPath in $appsToStart) {
Write-Host "检查路径: $appPath"
if (Test-Path $appPath) {
try {
Write-Host "正在启动: $appPath ..." -ForegroundColor Yellow
# 如果路径包含空格且有参数,Start-Process 可能需要特殊处理
# 但对于简单路径或 .lnk 文件,通常直接传递即可
# 如果遇到问题,可能需要拆分路径和参数
Start-Process -FilePath $appPath -ErrorAction Stop
Write-Host "已尝试启动: $appPath" -ForegroundColor Green
} catch {
Write-Error "启动失败: $appPath - $($_.Exception.Message)"
}
} else {
Write-Warning "路径不存在,跳过: $appPath"
}
# 短暂暂停,避免同时启动过多进程可能带来的问题(可选)
# Start-Sleep -Milliseconds 500
}
}
Write-Host "`n--- 脚本执行完毕 ---"
#endregion 主逻辑
#region 清理工作
# 停止记录日志
Stop-Transcript
#endregion 清理工作
经过测试,应该是可以用的:
但是本人的clash是装在路由器上的,实际效果还得佬友验证了。
市面上关于自动启动管理软件
被这个帖子吸引进来后,首先是引发了自己的思考,同时也了解了佬友们给出的一些资料,其中关于windows的Autoruns竟然还有这个东西是感觉挺不错的。
回到这个需求,我觉得市面上大部分也都只会是类似延迟启动
的脚本或软件,但是真正做可靠自动化的,延迟
只能算是workaround。
但现在AI盛行,即使什么问题,都可以通过AI学习或辅助达到效果。
感谢佬,写了这么多。我有空去改改测测
ztasker
佬友可能理解错了,我联系下上下文说一下
windows这种OS运行程序不是打开了就能开始用的,比如说佬友你的需求是clash启动后再去启动其他的软件,从而保证其他软件网络正常(我暂且认为这是佬友的原始需求)
先说问题:即使是先启动了clash再启动其他软件,但clash启动后不是瞬间就能用,所以出现一种情况是,确实是clash启动后再启动的其他软件,但是依旧用不了(其他软件启动速度大于clash的情况)
上面cocolu佬友说的XYproblem我觉得就在这里,佬友的真正需求是想要让其他软件在clash正常运行,代理可用后启动,而不是clash启动后启动,但是佬友可能对这方面不是很了解然后就出现了xyproblem(想要解决x问题,但提问时提问者自己认为y是解决x的最好/可行方式,从而提问y,但实际上y可能不是解决x的好办法)
个人观点,供佬友参考
另:cocolu佬友提供的脚本原理可行,也就是通过自定义逻辑来定义 clash启动完毕
这个行为到底怎么判定
原来是这样。我误会大佬们了。谢谢大佬解释!!
我之前也有这样的需求,然后网上找到了这样一个小工具,不知道对你有没有帮助