dsh-plugin-genshin-launch
原神,启动! —— 给 DeepSeek Harness(DSH)装一个插件:每次打开 DSH,先零配置看看本机有没有装《原神》——
- 装了 → 停止下载,直接把游戏本体拉起来(本体起不来自动改起米哈游启动器)。这就是「打开 DSH 就启动原神」。
- 正在装 / 更新(登记了位置但本体还没下完)→ 也不下载,改为启动米哈游启动器让它继续。
- 没装 → 把启动器安装包下载到桌面,带 224MB 体积安全闸;下载不成退化成打开官方下载页。
一句话简介(可直接用作 GitHub 仓库 About):
DSH 插件:打开 DSH 时零配置探测本机《原神》,装了就直接启动游戏本体(起不来自动改起米哈游启动器),没装就下载启动器安装包到桌面。
╔══════════════════════════════════════════════════════════╗
║ 原神,启动! ║
╚══════════════════════════════════════════════════════════╝
[genshin-launch] 识别到 DSH 端口:3080(http://127.0.0.1:3080)
[genshin-launch] 探测 · HoYoPlay 启动器安装目录:D:\…\miHoYo Launcher
[genshin-launch] 探测 · → 采用 D:\…\YuanShen.exe(来源:registry:hyp:hk4e_cn)
[genshin-launch] 检测到已安装的原神(国服 / B 服):D:\…\YuanShen.exe
[genshin-launch] 已安装 → 停止自动下载,改为「打开 DSH 就启动原神」
[genshin-launch] 启动原神(gui-open):D:\…\YuanShen.exe(方式 spawn)
[genshin-launch] 原神已启动(pid 21456)
网页右下角还有一个金边小面板,实时显示「原神,启动! + DSH 端口 + 探测到的本体(掩码路径)+ 启动结果 / 下载进度」。
特性
方案二:打开 DSH 就启动原神
- 零配置探测:用户什么都不用设置。按「先快后慢、命中即停」的顺序找(见下),最快一档约 400ms,实测整条快档 0.5 秒跑完。
- 触发时机 = 浏览器真的把界面渲染出来的那一刻,不是宿主进程启动的那一刻。原因是本 profile 开了
patchReload: live:挂在宿主apply上的话,你每改一次配置就会再弹一次原神。 - 每个 DSH 进程只启动一次:落盘标记以「宿主 pid + 进程启动时刻」为键,热重载不会重复启动,刷新页面也不会重开游戏。
- 秒退就改起启动器:启动后守一个观察窗(默认 3 秒)。本体在窗口内就退出(典型原因:客户端版本过低要先更新)→ 自动改起米哈游启动器;启动器也起不来才报错。
- 已经在跑就不重复启动:用进程名问一次(尽力而为,问不到就当没在跑,绝不因为问不到而拒绝启动)。
- 绝不静默提权,但会请你授权:插件不会用
runas悄悄提权。真机实测:YuanShen.exe与launcher.exe的清单都是requireAdministrator,用spawn(CreateProcess 语义)去起它不会弹 UAC,系统直接拒绝、Node 报EACCES。所以spawn一旦被这类权限问题拦下,插件自动改走一次shell(等价于双击),由 Windows 弹 UAC——你点同意才提权,点拒绝就不启动。不想回退可以设retryShellOnElevation: false。 - 不把 DSH 的秘密交给游戏:启动游戏时用脱敏后的环境变量(
*KEY*/*PASSWORD*/*SECRET*/*TOKEN*/DSH_*全部剔除,口径与@deepseek-ai/dsh-subprocess的scrubbedParentEnv一致)。游戏不该拿到你的 API key。 - 路径隐私:日志、网页面板、独立窗口、状态文件里的路径一律掩码成「盘符:\…\末段文件名」;手填/扫盘得到的本体地址在盘上按当前用户 DPAPI 加密存储;启动器路径不落盘(用时现探测);详见 隐私。
方案一:没装就把安装包下到桌面
- 端口识别:注入宿主
webServer服务读host/port,--port 0由系统分配端口也能拿到;DSH_WEB_URL兜底。 - 自动找最新版:候选直链可用时,还会在同一版本目录里向上探测更新的
pcbackup序号(实测 319 → 320)。 - 体积安全闸:启动器安装包约 224 MiB。凡是体积与预期相差超过 50 MiB 的链接——不管它来自候选、缓存还是探测——都会被整条拒绝:不下载、不续传,连已经下了一半的
.part一起删掉。体积拿不到也默认拒绝。 - 断点续传 / 落盘后复检 / 优雅退化 / 零依赖:同 v0.2。
怎么找到「已安装的原神」:五档阶梯
全程本地只读:读注册表字符串、existsSync 判存在、列目录项名字。不读文件内容、不联网、不发给任何模型。
| 档 | 做什么 | 实测开销 |
|---|---|---|
0 config |
配置里手填的 gameExe / gamePath(最高优先级,自测也用它) |
0ms |
1 registry |
读 HoYoPlay 的 HYP 树,取 hk4e_* 键下所有像盘符路径的值;再点查 3 个卸载记录根 × 4 个可能键名 |
~400ms |
2 paths |
每个盘根 + 每个顶层目录 × 几个常见安装目录名 | ~50ms |
3 scan |
卸载记录全量扫描(3 次 reg query /s)+ 有界扫盘(默认深度 ≤ 4,预算 20s) |
数秒 ~ 20s,只在前两档全落空时才跑,结果落盘 |
想彻底关掉扫盘:detectSources: ['config','registry','paths']。首次跑完会把「没找到」这个结论缓存 24 小时,之后每次开 DSH 都秒开。
几个实测踩出来的坑(决定了上面的设计)
- 注册表和卸载记录会残留,绝不能单独采信。 一台机器上「鸣潮」早卸载了卸载记录还在;
HKCU\Software\Classes\BetterGI指着一个已经删掉的目录;米哈游自己的HYP\standalone\14_0\hk4e_cn键存在但一个值都没有(现役布局其实在HYP\1_1)。所以任何读到的路径都必须立刻用文件系统复核。 - 值名不猜。 实测现役 HoYoPlay 1.18.0.380 把游戏路径记在
HKCU\Software\miHoYo\HYP\1_1\hk4e_cn的GameInstallPath下;但代码不按值名取,只要求「在hk4e_*键下、长得像盘符路径」——米哈游哪天改了值名也不会瞎。 - 不查
HKCU\Software\miHoYo\原神。 那个键里全是游戏自己的 Unity PlayerPrefs 和MIHOYOSDK_*加密 blob,不含安装路径(把全部REG_BINARY按 UTF-8/UTF-16 解过一遍找盘符路径,0 命中),而reg query它要跑 20 秒(输出 929KB 的十六进制倾倒)。放进阶梯等于每次开 DSH 塞一颗 20 秒的地雷。 reg.exe的输出编码跟着控制台代码页走。 中文 Windows 常见 936(GBK),也可能是 65001(UTF-8);直接按 UTF-8 解会把中文安装路径解成乱码。做法:统一先chcp 65001再查,输出就是确定的 UTF-8。- 进程启动开销才是大头。 点查「3 个卸载记录根 × 4 个键名」如果各起一次
cmd+reg,全落空时白花 800ms;串成一条cmd /c之后只剩一次进程启动。同理,固定候选路径从「每个组合一次existsSync(500 多次 stat,4.5 秒)」改成「每个顶层目录只readdir一次再比对(几十次,50ms)」。
「装了」「正在装」「没装」是三件事
中间那档很容易被忽略,但代价很实在:本体 exe 还没下下来时,如果只判「没装」,插件会去下一个 224MB 的启动器安装包——而启动器早就装好了。
所以探测结果有三个状态:
| 状态 | 判据 | 插件行为 |
|---|---|---|
ready |
YuanShen.exe(国服/B服)或 GenshinImpact.exe(国际服)在位 |
启动本体 |
incomplete |
结构指纹 ≥ 2 条:有 YuanShen_Data\、有 pkg_version、有 mhypbase.dll/rtlbase.dll、config.ini 里有 game_version= |
不下载,启动米哈游启动器让它继续 |
| 没找到 | 上面都不满足 | 下载启动器安装包(方案一) |
要求「≥ 2 条指纹」是有意的:原神本体 60GB+,把随便一个带 config.ini 的目录误判成原神,代价比漏判高得多。
安装
从 GitHub 直接装(推荐,可固定版本):
dsh plugin --profile web add github:Link258QAQ/dsh-plugin-genshin-launch
# 固定到某个 tag:
dsh plugin --profile web add github:Link258QAQ/dsh-plugin-genshin-launch#v0.4.0
本地开发用 link::
dsh plugin --profile web add "link:D:\path\to\dsh-plugin-genshin-launch"
装完下一次 dsh --profile web 启动时自动跑一遍。
卸载:
dsh plugin --profile web remove dsh-plugin-genshin-launch
插件 ID 是
genshin-launch,包名dsh-plugin-genshin-launch。 用link:安装时,改本目录的代码下次启动就生效,不用重装。 也可以在 DSH Market 里搜dsh-plugin-genshin-launch(收录审核通过后可见)。
装之前请注意
- 如果本机装了原神,这个插件会在你每次打开 DSH 界面时把游戏拉起来。嫌烦就在配置里把
launchGame设成false,或者直接卸掉插件。 - 没装原神时,它真的会下 224 MB 到你的桌面(可以改成别的目录或改成只打开链接)。
- 从 v0.3 及更早版本升级:首次启动会自动做一次隐私迁移——桌面上老配置的本体地址搬进加密存储(
%LOCALAPPDATA%\dsh-genshin-launch),老配置里的冗余明文路径字段被清除,桌面遗留的dsh-genshin-launch-*.json(status/detect/session)会被删掉。功能不变,只是这些明文文件从此消失。 - 如果安装时 pnpm 需要重新解析依赖树,而你的网络访问不了 GitHub(
codeload.github.com),安装会失败并回滚。先确认 GitHub 通,或者按下面的「不动 pnpm 的装法」手工接线。
link: 安装本质就是「package.json 加一条依赖 + bundles 登记 + 目录联接」,可以手工做:
- 在
$DSH_HOME\profiles\web\package.json的dependencies里加:
并在"dsh-plugin-genshin-launch": "link:D:/path/to/dsh-plugin-genshin-launch"dsh.profile.bundles数组里加一项"dsh-plugin-genshin-launch"。 - 建目录联接:
cmd /c mklink /J "$env:USERPROFILE\.dsh\profiles\web\node_modules\dsh-plugin-genshin-launch" "D:\path\to\dsh-plugin-genshin-launch" - 重启 DSH。
自检(装原神之前就能先验证启动链路)
插件带一个不依赖 DSH 的自检命令,把探测阶梯和启动各跑一遍并打印全过程:
# 只探测,看每一档查了什么、为什么没命中
node tools/selfcheck.mjs
# 拿任意一个程序当靶子,连「启动」一起验证(--kill 跑完把它收掉,别留窗口)
node tools/selfcheck.mjs --exe "D:\games\Shawarma\Shawarma Legend.exe" --launch --kill
# 换另一种启动通道(cmd /c start,双击语义)
node tools/selfcheck.mjs --exe "...\某程序.exe" --launch --kill --method shell
# 跳过最贵的扫盘那一档
node tools/selfcheck.mjs --no-scan
# 需要拿完整路径排错时(默认掩码成「盘符:\…\末段」,方便把输出直接贴进工单)
node tools/selfcheck.mjs --no-mask
退出码:找到(并启动成功)= 0,否则 1。
配置
在 $DSH_HOME/profiles/web/cordis.patch.yml 里按 id 覆盖:
- id: genshin-launch
name: dsh-plugin-genshin-launch
config:
# —— 方案二:打开 DSH 就启动原神 ——
launchGame: true # false = 不自动启动
launchTrigger: gui # gui = 浏览器打开界面时启动;host = 宿主进程一启动就启动
launchMethod: spawn # spawn = 直接起 exe(可判定成败);shell = cmd /c start(双击语义)
retryShellOnElevation: true # spawn 因「清单要管理员」被拦(EACCES)时,自动改走 shell 弹 UAC 一次
launchWatchMs: 3000 # 观察窗:这段时间内就退出算失败 → 回退去起启动器
fallbackToLauncher: true # 本体没起来就改起米哈游启动器
launchOncePerSession: true # 每个 DSH 进程最多启动一次
# —— 零配置探测 ——
gameExe: '' # 手填 exe 全路径(最高优先级)
gamePath: '' # 手填安装目录
detectSources: ['config', 'registry', 'paths', 'scan']
scanMaxDepth: 4
scanBudgetMs: 20000
extraRoots: [] # 额外的扫描 / 候选根目录
detectionCacheHours: 168 # 命中结果的缓存时长
negativeCacheHours: 24 # 「没找到」的缓存时长(只用来跳过扫盘那一档)
# —— 方案一:没装时下载 ——
download: true # false = 只打开下载链接
downloadDir: 'C:\Users\你\Desktop'
stateDir: '' # 状态/配置/缓存目录;默认隐藏的 %LOCALAPPDATA%\dsh-genshin-launch
expectedInstallerBytes: 234881024
sizeToleranceBytes: 52428800
openFileWhenDone: true
openFallbackWhenFailed: true
skipIfInstalled: true # false = 无视安装状态,照旧下载
方案二
| 字段 | 默认 | 说明 |
|---|---|---|
launchGame |
true |
总开关;false 时只探测不启动 |
launchTrigger |
gui |
gui = 浏览器把界面渲染出来时启动(推荐);host = 宿主进程一启动就启动 |
launchMethod |
spawn |
spawn = spawn(exe, {detached, stdio:'ignore'}),能拿到 pid 与 error/exit,是唯一能判定「秒退」的通道;shell = cmd /c start "" <exe>,走 ShellExecute(清单要求管理员时由系统弹 UAC),代价是拿不到子进程句柄、只能靠进程名轮询 |
retryShellOnElevation |
true |
spawn 被系统按「需要提权」拦下(EACCES / 错误码 740)时,自动改走一次 shell 弹 UAC。设 false 则不自动回退(仍会先试 spawn,只是权限失败后不再自己走 shell) |
launchWatchMs |
3000 |
观察窗长度 |
fallbackToLauncher |
true |
本体没起来就改起米哈游启动器 |
launchOncePerSession |
true |
每个 DSH 进程最多启动一次 |
gameExe / gamePath |
空 | 手填路径,优先级最高(自测 / 特殊布局用)。落盘时按当前用户加密;界面里只回显掩码形式 |
detectSources |
全开 | 想关掉扫盘就删掉 'scan' |
scanMaxDepth / scanBudgetMs |
4 / 20000 |
有界扫盘的深度与时间预算 |
extraRoots |
[] |
额外的扫描 / 候选根 |
detectionCacheHours / negativeCacheHours |
168 / 24 |
命中缓存 / 未命中缓存时长 |
方案一 / 通用
| 字段 | 默认 | 说明 |
|---|---|---|
enabled |
true |
总开关;false 时插件完全不动作,网页面板也不出现 |
download |
true |
false = 只打开直链 |
downloadDir |
桌面 | 目标目录;留空则自动找 Desktop / 桌面 / OneDrive 桌面 |
stateDir |
%LOCALAPPDATA%\dsh-genshin-launch |
状态/配置/缓存目录(含加密后的本体地址);测试或特殊环境可指到别处 |
url |
内置国服启动器直链 | 第一优先候选 |
extraUrls |
[] |
追加候选直链 |
probeLatest / probeStart / probeAhead |
true / 0 / 1 |
pcbackup 序号向上探测 |
resume |
true |
断点续传 |
expectedInstallerBytes |
224 MiB | 体积安全闸的预期值 |
sizeToleranceBytes |
50 MiB | 允许的体积偏差;超出 → 整条链接拒绝 |
minInstallerBytes / maxInstallerBytes |
0(自动推导) |
想直接指定上下限就填这里 |
allowUnknownSize |
false |
服务端不给 Content-Length 时是否放行 |
openFileWhenDone |
false |
下载完打开文件所在目录 |
openFallbackWhenFailed |
true |
失败时打开官方下载页 |
fallbackUrls |
['https://ys.mihoyo.com/launcher', ...] |
兜底打开的页面 |
useCache / cacheTtlHours |
true / 168 |
安装包链接解析缓存 |
skipIfInstalled |
true |
装了原神是否跳过下载(false = 无视安装状态照旧下载) |
clientNotice / clientNoticeSeconds |
true / 20 |
网页右下角面板 / 终态后自动关闭秒数 |
链接为什么会「自动更新」
米哈游没有给启动器安装包提供公开的“最新版”接口:游戏包有 hyp-connect API
(getGamePackages / getGameBranches),但启动器安装包只挂在 CDN 的版本目录下,
目录名是「时间戳_随机 token」,无法推导。实际可用的规律是:
- 你给的直链只要还活着就继续用(
HEAD检查 200 + 体积检查); - 同一版本目录下的
pcbackup<NNN>是顺序发布的安装包备份序号,号越大越新 (同一个安装器版本会同时挂 316/317/318/319/320 多个备份)。
所以插件先用你的直链,再顺手往上探一位,能拿到更新的就用更新的(实测 319 → 320); 如果你的直链失效了,就一直往上找到还存在的最大的序号。探测结果缓存 7 天。
诚实的边界:如果米哈游换了整个版本目录(新的时间戳 + token)并下掉旧目录,
pcbackup 往上探也没用,这时插件会按设计退化成打开官方下载页。
隐私与数据处理
本插件只在你本机工作,全程不联网上传任何个人信息(下载方案一从米哈游官方 CDN 拉公开安装包除外)。v0.4.0 起,对「可能沾到用户隐私的落盘与显示」做了系统整改:
落盘(磁盘上留什么)
- 只保留两样必须持久化的东西:① 原神本体地址(
gameExe,功能上必须知道它在哪才能启动);② 没装时下载的安装包地址(官方 CDN 直链,是公开链接、不含个人信息)。 - 本体地址在盘上按当前 Windows 用户加密(DPAPI
CurrentUser作用域,见lib/privacy.js)。别的用户 / 别的机器拿到这个文件解不开。DPAPI 不可用时(极端受限环境)如实降级为明文并在encryption字段标出来,绝不假装加密。 - 启动器路径不落盘:本体起不来要「改起启动器」时,从本体目录现推一次(
locateLauncherNear),用完即走。 - 配置格式 v1→v2 自动迁移:老版本把
scanFoundExe / installDir / gameDir / launcherPath等一堆明文路径写在桌面 JSON 里。v0.4 打开老配置时会自动把这些冗余字段清掉、把本体地址并进加密的secrets,并删除桌面上遗留的老状态文件(status / detect / session / window 脚本)。 - 临时残留自动清扫:注册表 / 进程列表的捕获输出(
%TEMP%\dsh-genshin-launch-*.out)在插件启动时扫一遍,删掉上一进程的残留(60 秒内的在途文件不动,避免抢正在写的那份)。 - 状态目录从桌面挪到隐藏的
%LOCALAPPDATA%\dsh-genshin-launch(可用stateDir覆盖;桌面里那种「谁都能翻一眼」的明文 JSON 从此不再产生)。
显示(日志与界面露什么)
- 日志和界面(网页面板、DSH 插件卡、独立窗口)里的路径一律掩码:完整路径压成「盘符:\…\末段文件名」,例如
C:\Users\example\Games\…\YuanShen.exe→C:\…\YuanShen.exe。用户名、中间目录结构都不出现。 - URL(
http://127.0.0.1:3080、官方下载页)不受影响——它们不是文件路径,不会被误掩码。 - 想改路径:因为界面只显示掩码,需重新粘贴完整路径(不能拿掩码串回填,否则会把
C:\…\xxx.exe当完整路径写回去;这一点在网页面板和独立窗口里都做了处理)。 - 自检
tools/selfcheck.mjs默认也掩码,方便你把输出直接贴进工单而不泄露本机目录;要排错拿全路径时加--no-mask。
一句话:盘上只留功能必需的两类地址且能加密就加密,其余能不存就不存;日志和界面只显示掩码。
已知限制与风险(请在装之前读一遍)
- 反作弊很在意「谁把你拉起来的」。 社区实测(2025 年「千星奇域」之后):第三方启动器会在进入游戏约 3 分钟后触发游戏内弹窗「检测到非法工具,请重启机器。错误码:10612-4001」;把自写程序改名成已知第三方工具的名字能复现,说明它至少部分依赖父进程名字黑名单。DSH/Node 不在已知名单里(Collapse 这类正经第三方启动器据报也不在),所以判断风险较低,但这属于会动到检测规则的东西,不是我们能保证的。
- 想更保守:
launchMethod: shell(父进程变成短命的cmd.exe,语义等于双击),代价是失去「秒退判定」。 - 真要完全规避:
launchGame: false,只用方案一。
- 想更保守:
- 原神本体与米哈游启动器都要求管理员权限(真机已确认)。
YuanShen.exe/launcher.exe的清单是requireAdministrator:用spawn直接起会被系统拒(EACCES),不会弹 UAC。插件的处理是——spawn因权限失败后自动改走一次shell,由 Windows 弹 UAC,你点同意才提权;点「否」就什么都不做。插件自己从不静默runas(守「绝不主动提权」)。不想自动回退就设retryShellOnElevation: false。 - 直接起游戏本体会跳过启动器的更新检查。 客户端版本过低时游戏会自己报错退出——这时观察窗会捕获「秒退」并自动改起启动器。
tasklist在某些受限环境里会被拒(Access denied)。 这时「是否已在运行」判定退化为「不知道」,插件会选择照常启动而不是拒绝启动。- HoYoPlay 的注册表布局会变。 我们已经见过
HYP\standalone\14_0\hk4e_cn(空残留)和HYP\1_1\hk4e_cn(现役)两种;代码枚举整棵树并靠叶子名认游戏,但米哈游再改一次结构仍可能需要更新插件。 - 有界扫盘只认目录名和几个结构指纹,不读文件内容、不联网。装在极其古怪的目录里仍可能漏;这时用
gamePath/gameExe手填,或把它加进extraRoots。
自测
npm test # 体积安全闸 + 配置 v2 加密/迁移 + 隐私模块(掩码/DPAPI/临时清扫)+ 探测/启动纯逻辑
npm run smoke # 宿主半侧集成冒烟:会真的启动一次靶子程序,跑完自动收掉(状态隔离在临时目录)
npm run smoke 用假的 ctx 把 apply() 拉起来,然后像浏览器那样走一遍路由,覆盖:四条浏览器侧接线是否注册、token 注入与幂等、启动路由的四种拒绝(错 token / 跨站 Origin / 非 POST / 非回环)、GUI 触发、启动成功、幂等(第二次触发不重复拉起)、状态文件落盘、秒退识别、目标不存在时报错而非崩溃。
验证记录
| 项 | 结果 |
|---|---|
| 端口识别 | 真实启动 dsh --profile web --no-open --port 3099,插件打印 识别到 DSH 端口:3099;/dsh-genshin-launch/status 返回 endpoint.port = 3099 |
| 最新版解析 | 种子 pcbackup319 可用 → 向上探测发现 pcbackup320 → 实际下载 320 那份 |
| 下载 | 223.5 MB 用时约 15s,落盘字节数与 CDN 一致,文件头是 MZ(合法 PE) |
| 体积安全闸 | 2 MiB / 900 MiB / 体积未知 → 全部拒绝;234382248 字节的真实安装包 → 放行;把预期改成 2 MiB 后同一文件放行(闸门可配置,不是写死) |
| 断点续传 | 造 1.5 MiB .part 后重跑,最终字节数与完整下载一致 |
| 落盘复检 | 体积不符会删文件并报错,不会把半截文件当成功 |
| 桌面不可写 | 自动改到工作区下载并打开资源管理器(模拟不可写目录实测通过) |
| index 注入 | 带 token 打开页面,HTML 里确实多出 <script defer src="/dsh-genshin-launch/client.js?token=…"></script> |
| 安装/卸载 | dsh plugin add/remove 均干净,卸载后 profile 的依赖与 bundles 完全还原 |
| 零配置探测(真实安装) | 真机装了 HoYoPlay 1.18.0.380 + 原神:从 HYP\1_1\hk4e_cn\GameInstallPath 读到游戏目录,并从 HYP\1_1\InstallPath 精确找到 launcher.exe;快档 0.5 秒跑完 |
| 「安装中」识别 | 真机在本体还没下完时(有 YuanShen_Data\、pkg_version、mhypbase.dll、rtlbase.dll、config.ini 里 game_version=,但 YuanShen.exe 不在)→ 判定 incomplete,不会去白下 224MB 安装包 |
| 启动通道自验证 | 用「靶子程序自己写标记文件」的方式验证(不靠数窗口):spawn ✅、cmd /c start ✅、explorer.exe file-uri ❌、rundll32 FileProtocolHandler ❌、Start-Process ❌(后三者在 DSH 沙箱内起不来;宿主里未必如此,但不作为主通道) |
| 真启动一次 | spawn 起真实 GUI 程序 → 拿到 pid、窗口出现、MainWindowTitle 正确;shell 通道 → cmd 退出码 0 |
| 注册表编码 | 中文 Windows 下 reg.exe 按 OEM 代码页输出:实测本机是 65001 而常见中文机是 936;统一 chcp 65001 后输出确定为 UTF-8 |
| 性能 | 探测快档 21s → 0.5s(砍掉 20 秒的 HKCU\Software\miHoYo\原神、把 12 次注册表查询合成 1 次、固定候选路径从 500+ 次 stat 改成几十次 readdir) |
| 环境变量脱敏 | 单测断言 *KEY* / *TOKEN* / DSH_* 不会传给游戏进程,PATH 保留 |
| 幂等 | 标记文件以「宿主 pid + 进程启动时刻」为键;patchReload: live 下热重载不会重复启动 |
| 宿主半侧集成冒烟 | npm run smoke:四条浏览器接线注册 ✅、token 注入且幂等 ✅、启动路由 4 种拒绝 ✅、GUI 触发→启动成功(拿到真实 pid)✅、第二次触发被幂等挡住 ✅、状态文件落盘 ✅、秒退识别为 early-exit ✅、目标不存在报 spawn-error 不崩 ✅ |
| 路径掩码(日志+界面+状态文件) | tests/privacy.test.mjs + 冒烟实测:宿主日志 / 状态 JSON / 网页面板 / 独立窗口 / DSH 配置卡 / 自检输出都只见 盘符:\…\末段;断言盘上没有用户名和中间目录;URL(http://127.0.0.1:3080)不被误伤 ✅ |
| 配置 v2 加密落盘 + v1 自动迁移 | 单测:gameExe/gamePath 不再以明文字段落盘(进 secrets,DPAPI 可用=dpapi 前缀密文,不可用=标注 plain);老 v1 明文配置(含 scanFoundExe/launcherPath/installDir 等冗余字段)打开即迁移、冗余字段清除、桌面遗留老文件删除(stateDir 为默认时)✅ |
| 启动器不落盘 | 代码走查:探测缓存 v2 只留 {found,registered,secrets(加密 exePath),flavor,source,checkedAt,scanDone},读旧缓存时 installDir/gameDir/launcherPath 一律丢弃;回退起启动器走 locateLauncherNear 现场推 ✅ |
| %TEMP% 残留清扫 | tests/privacy.test.mjs:造一个 5 分钟前的 dsh-genshin-launch-*.out 与一个新鲜的,跑一次 sweep——旧的删、新的(60s 内)不动 ✅ |
| DPAPI 真机 | 沙箱里 spawnSync powershell.exe EPERM → 按设计降级明文(round-trip 仍通,测试两种分支都覆盖);真机 DPAPI 加密路径由用户自行验证(本轮整改后首次在真机打开 DSH 时看 %LOCALAPPDATA%\dsh-genshin-launch\dsh-genshin-launch-config.json 的 encryption 字段应为 dpapi) |
目录结构
dsh-plugin-genshin-launch/
├── package.json # dsh.bundle.patch 声明,DSH 凭它识别为 profile 层
├── cordis.patch.yml # 挂载声明(insert 一行 genshin-launch)
├── lib/
│ ├── index.js # 宿主半侧:编排、分流、路由、index 注入、启动路由
│ ├── detect.js # 零配置探测阶梯 + 结构指纹复核 + 有界扫盘 + 启动器现探(不落盘)
│ ├── registry.js # 只读注册表:编码处理、解析、批量查询
│ ├── launch.js # 启动通道:spawn / shell、观察窗、进程轮询、环境变量脱敏
│ ├── download.js # 下载器:Range 续传、进度、大小校验(方案一)
│ ├── size-guard.js # 体积安全闸:224MB ± 50MB,越界整条拒绝(方案一)
│ ├── resolve.js # 链接解析:候选校验 + pcbackup 向上探测 + 缓存(方案一)
│ ├── exec.js # 子进程执行 + 文件式输出捕获(避开沙箱的管道限制)
│ ├── store.js # 配置持久化:v2 格式,路径进 DPAPI 加密 secrets,v1 明文自动迁移
│ ├── privacy.js # 隐私原语:maskPath / maskPathsInText / protect / unprotect / sweepTempFiles
│ ├── questions.js # 问答通道(扫盘同意、体积宽档确认——面板和独立窗口共用)
│ ├── window.js # 独立 WinForms 窗口的拉起 / 置顶 / 收尾
│ └── client.js # 浏览器半侧:右下角面板 + 「界面已打开」上报
├── client/
│ └── index.js # DSH 插件栏里的 React 配置卡
├── assets/
│ └── standalone-window.ps1 # 独立窗口的 WinForms 脚本(渲染掩码状态、不回填掩码路径)
├── tools/
│ └── selfcheck.mjs # 不依赖 DSH 的自检命令(默认掩码,--no-mask 看全路径)
└── tests/
├── size-guard.test.mjs
├── store.test.mjs # v2 加密格式、v1→v2 迁移、坏文件兜底
├── privacy.test.mjs # 掩码不泄露 / DPAPI round-trip 或降级 / 临时残留清理
├── detect.test.mjs
└── apply.smoke.mjs # 宿主半侧集成冒烟(用 stateDir 隔离到临时目录)
免责声明
本项目是 DSH 的第三方插件,与米哈游 / HoYoverse / DeepSeek 无任何关联。 它做两件事:零配置定位本机已安装的《原神》并按你的设置启动它;或在没装时把官方 CDN 上的公开安装包直链下载到你指定目录(下载不成则打开官方下载页)。 《原神》及相关名称、素材归米哈游所有;请遵守游戏官方的用户协议。使用本插件启动游戏所产生的任何后果(包括但不限于反作弊判定)由使用者自行承担。
No comments yet. Be the first to write one.