事件查看器里那一行「故障模块」,我盯着看了三遍才确认:twinui.pcshell.dll。
不是我们的 DLL。
那阵子在打磨 0.34 系列的外壳扩展,版本号走到 8 到 10 那一段,陆续有用户反馈:装完七亿压缩,Win11 上资源管理器开始反复崩。不是装的时候崩,是装完之后用着用着就崩,有时候右键点一下都能把 explorer 带走。
第一次,我怀疑是我们往右键菜单里自绘的那个图标。道理也顺:崩溃是新版本才有的,而自绘图标正好是那版新加的,换成最简单的纯文本菜单总行吧。撤掉图标,重新打包,让人再装——还是崩。
第二次,我动了整体回退的念头。既然说不清是不是我们引起的,最稳的做法不就是把整个外壳扩展退回去吗,先让用户能用。老大把我按住了:别急着退,先把事件查看器里的崩溃模块名取出来再说。
现在想想,这两步其实是一码事,都是在猜。第一次猜是图标,第二次猜是「反正可能是我们」,根因一次都没真正看过。
twinui.pcshell.dll 是 Win11 新的菜单/壳组件。故障模块指向它,说明崩的进程虽然是 explorer,但出问题的那一帧不在我们的代码里——是 Win11 在调和多家传统外壳扩展(我们,加上 360 那类常驻的)的时候崩的,我们只是恰好排在触发它的位置上。这件事在拿到模块名之前,靠坐在这儿想,一辈子也想不出来。
后来才慢慢理清:外壳扩展是活在 explorer 进程里的,我们的 DLL 在里面的一举一动,跟在一个独立的测试进程里调 COM,是两套完全不同的环境。测试里好好的,真机上崩,这个落差我算是吃够了。
修法走了两条。一是把暴露面收窄——不挂虚拟命名空间(Folder 键)那一套,少给 explorer 几条能调我们的路径。二是干脆把整个外壳扩展重写了一遍:收成单个文件,外面套一层 SEH,把崩溃圈在我们自己进程里,不让它把整个 explorer 一起带走。第二条是决定性的,改完之后那批 Win11 的反馈就下去了。
我们做 7eZip 的这拨人,同时还维护着七亿批量远程管理工具(远程运维那一套),两边撞上的毛病有时候是同一个路数:都在别人的进程里干活,崩了都不好查,也都容易先怪自己人。这次记住的就一句,写在纸上像废话——拿到故障模块名之前,不要猜根因。那两天我实实在在猜错了两次,一次撤图标,一次差点把整块扩展退回去。
前面写过一篇右键菜单第 0 项永远点了没反应,同一个外壳扩展上出的另一个坑。软件本身在七亿压缩的站点上,装完不改主页、不弹广告。
两次误判搭进去的时间,比修这个 bug 本身还长。
评论