第 ⑫ 章 · 调试、部署与现代化迁移
收尾章——如何调试跑在 explorer/dllhost/prevhost 里的扩展、per-user 与 per-machine 注册、MSIX/稀疏包部署,以及一张“旧接口 → 新接口”的迁移对照表。
前面每章一个扩展点。这一章把散落的工程问题收一下口:怎么调试、怎么干净地注册、怎么部署,以及——本指南从头到尾的主线——把 20 年前的老写法迁移到 Win10/11 的新接口。
一、调试:你的 DLL 跑在别人的进程里
Shell 扩展是进程内 COM 组件,被宿主进程加载。调试的第一步是搞清楚“宿主是谁”:
| 扩展类型 | 宿主进程 | 怎么调 |
|---|---|---|
| 右键菜单 / 图标 / InfoTip / 属性页 | explorer.exe | 附加到 explorer;改完 DLL 前先 taskkill /f /im explorer.exe 再重启 |
| 缩略图 / 属性处理器 | dllhost.exe(COM Surrogate) | 附加到对应的 dllhost 实例 |
| 预览处理器 | prevhost.exe | 独立进程,直接附加最省心 |
调试期开隔离,给 CLSID 加一个空的 AppID 值即可让系统用 dllhost 托管:
HKCR\CLSID\{你的CLSID}\ AppID = {你的CLSID}
HKCR\AppID\{你的CLSID}\ DllSurrogate = "" (空字符串 = 用默认代理 dllhost)二、注册:per-user 还是 per-machine
regsvr32 默认写 HKEY_CLASSES_ROOT,需要管理员。现代推荐 per-user 注册——写 HKCU\Software\Classes,免管理员、卸载干净、不影响其他用户:
HKCU\Software\Classes\CLSID\{CLSID}\... ← 组件本体
HKCU\Software\Classes\.ext\shellex\... ← 关联本指南的示例为求简洁写的是 HKCR(= 管理员 per-machine)。真实产品优先 per-user,除非扩展确实要对所有用户生效。
在非默认(non-per-user)场景,企业环境可能启用“仅允许已批准的扩展”策略(HKLM\...\Shell Extensions\Approved)。个人机通常不受影响,但企业分发时要留意。
三、部署:从 regsvr32 到 MSIX
regsvr32 + 写注册表是经典做法,但 Win10/11 的现代分发是 MSIX / 稀疏包(sparse package):
- 声明式:扩展点写在
AppxManifest.xml里(见 Win11 菜单章),系统按清单注册,不用手写注册表。 - 干净卸载:卸载包 = 所有注册项一起消失,不留垃圾。
- Win11 主菜单硬性要求:前面讲过,要进 Win11 那个新版右键主菜单,必须打包 + 用
IExplorerCommand,regsvr32的老菜单只会被折叠进“显示更多选项”。
所以现代扩展的典型形态是:IExplorerCommand 实现 + MSIX/稀疏包声明。老的 IContextMenu + regsvr32 仍然能用,但只活在“更多选项”的二级菜单里。
四、现代化迁移对照表
这是把老代码搬到 Win10/11 时最该记住的一张表——左边是本指南参考的 2004 年老文里的写法,右边是现在该用的:
| 目的 | 旧接口(已过时/受限) | 新接口(Win10/11 推荐) |
|---|---|---|
| 初始化——拿到目标文件 | IShellExtInit / IPersistFile | IInitializeWithStream → WithItem → WithFile |
| 缩略图 | IExtractImage | IThumbnailProvider |
| 列表额外栏目 | IColumnProvider(已移除) | 属性处理器 + IPropertyStore |
| 右键命令 | IContextMenu(进“更多选项”) | IExplorerCommand + 打包 |
| 数据关联 | 直接读文件句柄 | 优先 Stream,以便沙箱/云文件/隔离宿主 |
一条总原则:能用 Stream 就别用 File。IInitializeWithStream 让扩展跑在受限沙箱、云占位文件(OneDrive Files On-Demand)、隔离宿主里都不出问题;直接抓文件路径的老写法在这些场景会失效。这也是微软反复强调的方向。
结语
到这里,Windows Shell 扩展的主要扩展点就走完了一遍:从右键菜单、Win11 新菜单,到缩略图、图标,再到属性、提示、属性页、预览、拖放、图标叠加。每一章的完整可编译代码都在 shell-extension-demos 仓库里。
核心心法就三条:扩展跑在别人进程里,所以要快、要稳、要隔离;能用 Stream 初始化就别碰文件路径;面向 Win11 就上 IExplorerCommand + MSIX。