BeyondDimension / BeyondDimension/SteamTools

🐛[BUG] -clt proxy / -clt shutdown 对运行中的实例无响应,冷启动也不会按注释拉起程序

Open
#4,141 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
26.8k
Forks
1.7k
PR merge metrics
No merged PRs in 30d

Description

## 请认真检查以下清单中的每一项

- [X] 已经搜索过,没有发现类似的 issue
- [X] 已经搜索过文档,没有发现相关内容
- [X] 已经尝试使用过最新版,问题依旧存在
- [X] 使用的是官方版本(未替换及修改过安装目录程序文件)

### 🐛 描述

`src/BD.WTTS.Client/Startup/Startup.Commands.cs` 里有 `proxy` 命令,注释写的是「启用代理服务,静默启动(不弹窗口)」,另有 `-clt shutdown`(安全结束正在运行的程序)。常量在 `Startup.Constants.cs`(`clt_ = "-clt"`、`key_proxy = "proxy"`、`key_shutdown = "shutdown"`、`key_show = "show"`),服务端分支在 `Startup.Host.cs` 的 `case key_proxy` → `IProxyService.StartOrStopProxyService(bool)`。本机 Windows x64 3.1.0 安装目录里能搜到「启用代理服务,静默启动(不弹窗口)」这串字面量,所以应当是带这个功能的版本。

实测三点:

1. **有实例在跑时,命令送达了但没有任何作用。** 客户端退出码 0,而三项外部判据全部不变:hosts 里的 `# Steam++ Start` 段、443 的监听者(`Steam++.Accelerator`)、`curl -I https://github.com/` 的返回码。当天日志 `%Tmp%\Steam++\Logs\nlog-all-2026-09-12.log` 是跨实例连续追加的同一个文件,**21:56:33 之后直到 23:01:03 之间零新增行**,而这段时间内我投了 6 次 `-clt proxy` 各种写法与 1 次 `-clt shutdown`。也就是说主实例侧既没有成功日志也没有失败日志。
2. **没有实例在跑时,`-clt proxy -on` 不会把程序拉起来。** 客户端 1s 内退出(码 0),连续轮询 36s 进程数为 0、hosts 不变。按 `Startup.Commands.cs` 的注释这条路应当走「未启动 → 类似 `-silence` 逻辑」。
3. 中途一次 `-clt proxy -on` 之后进程数从 3 变 4 且未回收(我没能区分那是第二个完整实例还是子进程,不敢断言)。

顺带一个容易误伤使用者的点:不带任何参数启动时,`Startup.SingleInstancePipeline.cs:18` 是
`SendMessage(sendMessage?.Invoke() ?? (IsMainProcess ? key_show : ""))`,默认消息就是 `key_show`,
所以「想用命令行静默开启」而直接执行 `Steam++.exe`(不带 `-clt`)必然把主窗顶到前台。这本身是设计如此,但和 `proxy` 命令注释放在一起时很容易被当成同一条路。

### 📷 复现步骤

前置:正常启动程序并开启网络加速,确认 hosts 有 `# Steam++ Start` 段、`Get-NetTCPConnection -State Listen -LocalPort 443` 的持有者是 `Steam++.Accelerator`。

1. 执行 `Steam++.exe -clt proxy -off true`,等 20s
2. 复看上面三项判据 —— 本机全部不变,且当天日志零新增行
3. 把程序完全退出(管理员 `Stop-Process`,见下方补充),再执行 `Steam++.exe -clt proxy -on`,等 40s
4. 复看进程数与 hosts —— 本机为 0 进程、无变化

参数写法已排除是我语法错(用退出码当解析探针,`bogus-verb` 给 1 作对照):

| 参数 | 客户端退出码 | 主实例反应 |
| --- | --- | --- |
| `-clt proxy --off` | 1(解析失败) | 无 |
| `-clt proxy -off true` | 0 | 无 |
| `-clt proxy -off` | 0 | 无 |
| `-clt proxy`(想 toggle) | 0 | 无(`case key_proxy` 要求 `args.Length >= 2`,按源码本来就不该有反应) |
| `-clt shutdown` | 0 | 无 |
| `-clt bogus-verb` | 1(对照组) | — |

### 📄 日志信息

另一个观察:**每次开启加速都会刷 7~8 条同名异常,但加速最终仍然成功**。下面两段的栈逐字相同,前者来自 GUI 手点(与 hosts 修改时间 21:56:34 吻合),后者来自命令行冷启动(23:13:24,另一次 23:01:03、23:05:20、23:07:27 各一组,条数 7~8 条):

```
2026-09-12 23:13:24.7772|Error|StartOrStopProxyService|System.Threading.Tasks.TaskCanceledException: A task was canceled.
---> System.Threading.Tasks.TaskCanceledException: A task was canceled.
at System.Threading.Tasks.TaskCompletionSourceWithCancellation`1.WaitWithCancellationAsync(CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(...)
at System.Net.Http.RedirectHandler.SendAsync(...)
at System.Net.Http.SocketsHttpHandler.g__CreateHandlerAndSendAsync|115_0(...)
at System.Net.Http.HttpClient.g__Core|83_0(...)
--- End of inner exception stack trace ---
at System.Net.Http.HttpClient.HandleFailure(...)
at BD.WTTS.Services.Implementation.NetworkTestService.TestDNSOverHttpsAsync(String testDomain, String dohServer, DnsRecordType dnsRecordType, CancellationToken cancellationToken)
at BD.WTTS.Services.ProxyService.GetValidDNSAsync(String dns, CancellationToken cancellationToken) |
```

想确认这是 `ProxyBeforeDNSCheck` 的预期日志(DoH 探测失败按 Error 记账)还是异常路径。若属预期,建议这几条降级到 Debug 或补一条「哪个 dns、超时多少」的可读信息:自动化侧要靠日志判断「这次到底成没成」,现在只能退回去看 hosts 段和 443 的持有者。

### 🖼 截图

不放截图,避免把本机窗口标题和账号信息带出去;上面三项判据都能命令行复验,比图更省事。

### 🚑 其他信息

- 处理器体系结构:x64
- 系统版本号:Windows 11 专业版 25H2 Build 26200
- 下载渠道:本机安装在自定义目录(不是微软商店路径),具体渠道我无法从安装产物反推
- 程序版本:3.1.0(FileVersion 3.1.2025.0,`releases/latest` 也是 3.1.0)
- 是否包含独立运行时:否(安装目录内未见 hostfxr / hostpolicy)

补充一个绕法现状,也是提这个 issue 的原因:我这边「自动开」最后是绕到 **冷实例 + `ProgramStartupRunProxy=true`** 实现的(实测约 6s 起效,且 `MainWindowHandle=0`、不抢前台);但「自动关」没有优雅路径 —— 只能管理员 `Stop-Process`,而**被杀掉的实例不会还原 hosts**(本机实测留下 47 条 `127.0.0.1` 僵尸行,此时 GitHub 直接 `curl` 000),所以还得自己按 `# Steam++ Start` / `# Steam++ End` 标记把段剥掉,并且 hosts 在刚杀完会被短暂锁住、写入要重试。`CloseMainWindow()` 也不算退出路径,它只是缩进托盘、hosts 照旧。
如果 `-clt proxy -off` 与 `-clt shutdown` 能对运行中的实例正常响应,这两件事就都能优雅收口,也就没有必要用「杀进程 + 清 hosts」这种脏办法。

同源、都还 open 的几条相关 issue(现象不同,但都是「启动路径上的窗口/权限」这一类):#3805(每次启动都弹 UAC)、#2004(自启动强制最小化不生效)、#3650(开机弹窗)、#3316(开机自动加速遇 hosts 掉权限会反复弹网页)。

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with src/BD.WTTS.Client/Startup/Startup.Commands.cs and follow the proxy and shutdown paths through Startup.Host.cs, Startup.Constants.cs, and Startup.SingleInstancePipeline.cs. Reproduce the listed -clt commands on Windows while checking the process, hosts markers, port 443 listener, and logs. Done means running instances respond, cold-start proxy works as documented, and shutdown exits cleanly without leaving hosts entries behind.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
cli, desktop
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.