Repository navigation
Replies: 1 comment
|
第 4 步我核到了,而且有个现成的反例就在同一个文件里:这个文件知道 handler 会抛,只是没在那个位置防。
static void Visit(string path, Action<IHandler> visit) {
var extension = Path.GetExtension(path);
if (extension.Length == 0) return;
SHAssocEnumHandlers(extension, 0, out handlers);
...
Marshal.ThrowExceptionForHR(result);
Visit(path, delegate(IHandler handler) {
handler.GetName(out id); handler.GetUIName(out name);
但同一个文件的 static string IconData(IHandler handler, string id) {
try { handler.GetIconLocation(out source, out index); } catch (Exception) {图标路径那一步是逐项 catch 的。也就是说这个文件已经承认"某个 handler 的注册信息可能已经坏了",只是把这份容错用在了取图标上,没用在取名字上。修法就是把 关于第 6 步的 500,我没有核那条链( 顺带一个可以写进报告的判断依据: |
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Summary
在 Windows 桌面端点击"交付文件卡片"打开文件时,前端收到 HTTP 500,文件无法打开;但用
action=open的 POST 直接打开是成功的。根因链路:
GET /api/present.open去枚举该文件的"可用程序";dsh-native-command的List()(PowerShell + C# 适配器调SHAssocEnumHandlers);IHandler.GetName()会返回COMException: HRESULT E_FAIL;List()遍历 handler 时没有逐项容错,一处失败使整个调用抛出;workspacePathApplications把异常包成RemoteError("gateway/internal");handlePresentOpen的failureStatus()不认识该 code,折叠为 500,响应体恒为字符串Presented file unavailable.,且 catch 不记录任何日志。影响:任何安装了"注册信息已失效"的第三方软件的 Windows 用户,都会完全无法通过 UI 打开文件卡片,且无法自助定位原因。
Reproduction
最小可复现条件:该系统上存在一个 handler,其注册表指向的文件已不存在。
HKCU\Software\Classes\Applications\<App>.exe\shell\open\command注册、随后被移动或卸载的程序(本机案例:Cursor 从C:\Users\...\AppData\Local\Programs\cursor移到D:\ZACK\cursor,旧路径残留);SHAssocEnumHandlers枚举到(同一扩展名下其他 handler 正常);dsh-app://app/api/present.open?sessionId=…&seq=…&index=0→ 500。对照实验(用于区分"枚举"与"打开"两条分支):
Current behavior
GET分支返回 500,body 恒为Presented file unavailable.handlePresentOpen的 catch 既不打console.error也不附cause,--enable-logging同样抓不到List()内单点失败导致整个列表作废;workspacePathApplications也没有降级路径逐步插桩的实际输出(对
List()内各步骤单独 try/catch):注意:
SHAssocEnumHandlers与Next()均成功,失败仅发生在单个 handler 的GetName/GetUIName。同机其他 handler(记事本、Acrobat、Chrome、Edge、Figma 等)
GetName全部正常,说明接口约定本身没问题,是个别第三方注册不规范。修复该 handler 的注册路径后:
Expected behavior
建议(按投入从低到高):
List()逐 handler 容错:GetName/GetUIName抛错时跳过该 handler(或退化用GetIconLocation的路径作 id),不中断整个枚举。这是最小修复,且与"某个应用图标取不到不应让整个列表失败"的既有注释风格一致(PngFromIconSource已经这样处理了图标)。workspacePathApplications降级:枚举失败时返回空列表(200 []),让前端退化为"直接用默认程序打开",而不是 500。handlePresentOpen的 catch 至少console.error(name/code/message/cause),否则此类问题只能靠外部复现。附带的观察:当前 400 / 404 / 409 / 422 的语义划分是清晰的(坐标非法 / 事件或文件找不到 / 桌面桥不可用 / 路径映射失败),这一层设计没问题;问题集中在"枚举分支没有降级"和"catch 不可观测"。
Environment
0.2.1-rc.2(桌面端,app.asar内@deepseek-ai/dsh同为 0.2.1-rc.2)dsh-app://app/-STA,脚本由 DSH 生成)@deepseek-ai/dsh-native-command(List()/windowsFileApplications)、@deepseek-ai/dsh-api-session-controller(workspacePathApplications)、@deepseek-ai/dsh-client-ui-deliverables(handlePresentOpen)HKCU\Software\Classes下 6 处关联仍指向已不存在的旧路径本机缓解方式(供其他用户参考,非代码修复)
把失效 handler 的注册表路径改指真实位置即可,无需改 DSH、无需重启:
All reactions