Replies: 3 comments 1 reply
这条与 #7842 / #7860 是同一个子系统——建议合并,而不是各修一半1. 你指的那一层在哪里"打开方式"的应用列表由 2. 你这条的诊断价值:枚举与启动是两件事同一天已有两份报告落在同一条路径上,但症状各不相同:
⇒ 你这条把范围扩大到了"枚举"这一步,这是前两条没有覆盖的——所以它值得保留为独立报告,但建议明确写一句"这是同一条路径上的第三步",让维护者一次把这三处一起看。 3. 请补三样(能让"单个 handler 拖垮整个枚举"变成可判定)
第 3 条是关键:它把"我的机器上不行"变成"枚举必须逐项隔离"这条可验收的要求。 4. 一个建议无论最终是"逐项容错"还是"修那个 handler","读一个条目的元数据失败 ⇒ 整份列表不可用"都是一个应当被修的形状。建议把诉求写成:
5. 版本提醒
一条边界我确认的是该子系统由 |
|
补 PerryLink 要的三样(本机 0.2.0-rc.1 产物,Windows 11 / NTFS / PowerShell 7.6.6)。复现方式:把官方 1. 坏 handler 是哪一个 —— 不止一个,而且不止写字板
⇒ 本机至少是两族坏 handler:一个写字板遗留项,一个 Apex Legends 的关联项(后者我原报告里没提到,是这次探针才发现的)。共同点很关键: 2. 完整异常原文按官方 3. 对照实验:逐项隔离我没有卸载或改名任何注册项(避免改用户系统),改为把同一批 handler 逐项 try/catch:
⇒ 坏项被跳过后,列表完整可用(21–26 个应用)。「单个条目读取元数据失败 ⇒ 整份列表不可用」由此成立,修法就是逐项隔离。你提的诉求措辞我完全同意。 4. 一条时间线:同一路径上「启动」那一步刚修了,「枚举」这一步没修
对应的是 #7842 / #7860 的启动步骤( 但枚举这一步没有被覆盖: handler.GetName(out id); handler.GetUIName(out name); // 无 try/catch同一路径、两步,这次只修了后一步。建议维护者这次把两处一起看 —— 否则"打开方式"下拉仍会在这类机器上永远显示「无法获取应用列表」。 (探针脚本逐行对应官方 |
|
补一条对上一帖的更正 —— 我把那个坏项的来源查清了,它并不是"关联了这些扩展名"。 它不是被关联到 .txt/.png/…,而是注册成了"万能打开方式"该项下只有 同机两处旁证:这类项是安装器留下的前者是 Steam 的 Source 关联被游戏安装覆盖,后者是 Discord 的游戏集成建的 ProgID。 而 WORDPAD 那一族来自通配列表: 为什么这两个 handler 的
|
Uh oh!
There was an error while loading. Please reload this page.
摘要
Windows 桌面版上,Presented 文件卡片的「打开方式」下拉永远显示「无法获取应用列表」,
而同一台机器上目录级的
/open-in-app/apps路由是正常的(返回已安装应用列表)。根因:文件级枚举走的是另一条链 ——
session.workspacePathApplications→nativeFileApplications→Windows 分支用 PowerShell +
Add-Type现场编译 C#,通过SHAssocEnumHandlers枚举注册的 shell handler。其中对
IHandler.GetName/GetUIName的调用没有任何容错:只要注册表里存在一个这两个方法返回
E_FAIL的 handler(本机是一个写字板 WORDPAD 遗留关联项),异常就会冒泡,整个
List()失败 →nativeFileApplications抛错 → 前端把null当作 failed →显示
path.appsError(「无法获取应用列表」)。ASCII 与中文路径同样受影响,与路径编码无关。环境
@deepseek-ai/dsh@0.1.7-rc.1(打包版deepseek-harness-pkg@0.1.7-alpha.2)@deepseek-ai/dsh-native-command@0.1.7-rc.1复现
抛:
定位过程
SHAssocEnumHandlers本身是好的 —— 单独调用(同样的 IID 与签名)对所有扩展名都返回OK(enum);IHandler的方法临时改成[PreserveSig] int逐个读 HRESULT,坏 handler 立刻现形:0x80004005即E_FAIL。注意同一项的GetIconLocation是成功的 —— 坏的是GetName/GetUIName这两个。影响链(为什么用户看到的是「无法获取应用列表」而不是空列表)
nativeFileApplications抛错 →dsh-api-session-controller的workspacePathApplications包成RemoteError('gateway/internal')抛出 →dsh-client-ui-open-in-app的applications()catch 后return null→failed: apps === null,菜单渲染出path.appsError。注意对比:该方法开头
if (!this.canOpenPath()) return []—— 空数组不会显示这条错误。所以「无法获取应用列表」必然是抛错路径,这一点可以作为排查判据。
建议修复
给每次 handler 读取加容错,坏 handler 跳过而不是终止整个枚举:
Visit(path, delegate(IHandler handler) { string id, name; - handler.GetName(out id); handler.GetUIName(out name); + try { handler.GetName(out id); } catch (Exception) { return; } // 无名者无法被启动,跳过 + if (id == null || id.Length == 0) return; + try { handler.GetUIName(out name); } catch (Exception) { name = id; } + if (name == null || name.Length == 0) name = id; if (!seen.Add(id)) return;等价做法是把
IHandler.GetName/GetUIName声明改成[PreserveSig] int并显式检查 HRESULT ——同文件的
IconData(handler)已经用 try/catch 做了这种容错(注释写着 "Missing icon resources do not makethe application unusable."),说明这套策略是本项目接受的风格,只是没覆盖到
GetName/GetUIName。另外建议给
OpenRegistered(同一 C# 里另一处Visit回调)加同样的跳过逻辑,否则一个坏关联会让「用 X 打开」也一起失败。
附:定位用的最小探针(PowerShell 5.1,需
-STA)附:本机验证(结果脱敏)
按上面的建议打本机补丁后,同一调用不再抛错,返回该扩展名下的全部已注册 handler
(本机为 21 项;清单与具体应用名此处略去),且默认项被正确标记:
{ "installedHandlers": 21, "defaultResolved": true, "failed": false }(另注:
@deepseek-ai/dsh-native-command@0.1.7-rc.2—— npmnext—— 该处仍未修,补丁后 L632 仍是
handler.GetName(out id); handler.GetUIName(out name);。)All reactions