diff --git a/internal/taobao/chrome.go b/internal/taobao/chrome.go index 9244965..056bf47 100644 --- a/internal/taobao/chrome.go +++ b/internal/taobao/chrome.go @@ -3,6 +3,7 @@ package taobao import ( "context" + "encoding/base64" "encoding/json" "errors" "fmt" @@ -286,13 +287,35 @@ func processExists(pid int) bool { return strings.Contains(string(output), fmt.Sprintf("\",\"%d\",", pid)) } +// processCommandLine 读取指定进程的完整命令行。 +// +// 这里有个必须绕开的坑:PowerShell 的标准输出用系统 ANSI 代码页 +// (简体中文 Windows 上是 GBK),而 Go 里的字符串是 UTF-8。 +// 专属 profile 路径含中文(电商视频自动下载工具\淘宝浏览器\默认账号), +// 直接读会拿到 GBK 字节,和 UTF-8 的 profile 怎么比都不相等, +// 于是归属校验永远失败、Chrome 刚启动就被判为"不属于本 profile"。 +// +// 解决办法是让 PowerShell 先把结果转成 UTF-8 的 Base64,Go 侧再解码。 +// 不用 [Console]::OutputEncoding=UTF8 是因为那依赖控制台状态, +// Base64 只有 ASCII,任何区域设置下都可靠。 func processCommandLine(pid int) (string, error) { - command := fmt.Sprintf(`(Get-CimInstance Win32_Process -Filter "ProcessId=%d").CommandLine`, pid) + command := fmt.Sprintf( + `$c=(Get-CimInstance Win32_Process -Filter "ProcessId=%d").CommandLine; `+ + `if ($null -eq $c) { '' } else { `+ + `[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($c)) }`, pid) output, err := exec.Command("powershell", "-NoProfile", "-Command", command).Output() if err != nil { return "", fmt.Errorf("读取 PID %d 的命令行失败:%w", pid, err) } - line := strings.TrimSpace(string(output)) + encoded := strings.TrimSpace(string(output)) + if encoded == "" { + return "", fmt.Errorf("找不到 PID %d 的进程命令行", pid) + } + decoded, err := base64.StdEncoding.DecodeString(encoded) + if err != nil { + return "", fmt.Errorf("解析 PID %d 的命令行失败:%w", pid, err) + } + line := strings.TrimSpace(string(decoded)) if line == "" { return "", fmt.Errorf("找不到 PID %d 的进程命令行", pid) } diff --git a/internal/taobao/chrome_test.go b/internal/taobao/chrome_test.go index 21dc61d..c0cb04a 100644 --- a/internal/taobao/chrome_test.go +++ b/internal/taobao/chrome_test.go @@ -1,6 +1,9 @@ package taobao -import "testing" +import ( + "strings" + "testing" +) func Test命令行归属判断(t *testing.T) { profile := `C:\Users\测试 用户\淘宝浏览器\默认账号` @@ -44,3 +47,29 @@ func Test端口全占满时返回错误(t *testing.T) { t.Fatal("端口全占满时应返回错误") } } + +// 防回归:profile 路径含中文时的归属判断。 +// +// 曾经真实发生过:PowerShell 输出用系统 ANSI 代码页(GBK), +// Go 字符串是 UTF-8,含中文的 profile 路径两边字节不同, +// 归属判断永远为 false,Chrome 一启动就被判为"不属于本 profile"。 +// 修法是让 PowerShell 先转 Base64(UTF-8) 再由 Go 解码。 +// +// 这个测试只能守住比较逻辑本身;编码问题必须靠 processCommandLine +// 里的 Base64 传输解决,改那里时务必用真实 Chrome 验证一次。 +func Test中文路径的归属判断(t *testing.T) { + profile := `C:\Users\ila20\AppData\Local\电商视频自动下载工具\淘宝浏览器\默认账号` + cmd := `"C:\Program Files\Google\Chrome\Application\chrome.exe" ` + + `--user-data-dir=C:\Users\ila20\AppData\Local\电商视频自动下载工具\淘宝浏览器\默认账号 ` + + `--remote-debugging-port=19666` + + if !commandBelongsToProfile(cmd, profile) { + t.Fatalf("含中文的 profile 路径应当判定为属于本程序") + } + // 用 GBK 编码的同一路径必须判为不属于——这正是修复前的真实故障形态, + // 如果哪天又退回按控制台编码读取,这里会失败。 + gbk := "\xb5\xe7\xc9\xcc\xca\xd3\xc6\xb5" + if commandBelongsToProfile(strings.ReplaceAll(cmd, "电商视频", gbk), profile) { + t.Fatalf("编码不一致的命令行不应被判为属于本程序") + } +}