为什么 Windows Shell 上下文菜单处理程序会在 Windows 8/10 上破坏高级用户菜单 (Win+x)?

Why does Windows Shell context menu handler break power-user menu (Win+x) on Windows 8/10?

我的自定义 Windows shell 上下文菜单处理程序非常有用,适用于从 XP 到 7 的所有 Windows 版本,但在 Windows 8、8.1 和 10 上,安装它会破坏 Win+X 菜单(有时称为 "Power user menu",或 "Quick Access menu", or "WinX menu"): 当点击 Win+X,菜单按预期显示,但它的项目不再工作(当我点击它们时没有任何反应),除了底部的最后四个项目仍然按预期工作("Search", "Run", "Shut down/Sign out", "Desktop"):

我很快在 Google 上发现,对于大量 shell 不是 "compatible"[=44= 的扩展来说,这是一个众所周知的问题] Windows 8/10。但遗憾的是,我只发现应用程序用户在谈论这个问题及其 "solutions",而没有开发人员在谈论这个。而这些用户提出的两个"solutions"是:

  1. 注销此 shell 扩展程序
  2. 正在卸载注册此 shell 扩展程序的应用程序(这导致解决方案 1...)

例如,请参阅 this, this, or this 阅读人们谈论这个问题。

注意:我的 shell 扩展名适用于 * 文件类型,这意味着所有文件。

几天后,我在 shell 扩展源代码中找到了这个问题的原因,所以我认为它可以帮助其他开发人员在 Whosebug 上分享它,作为一个自答题(我没有'找到这个问题)。请参阅上面的答案。

我先看了一下微软提供的shell extension sample code(不会导致这个问题),和我的代码对比,逐步把我的部分代码替换成微软的代码,每次替换后测试.

我发现阻止高级用户菜单工作的是你在IContextMenu接口的方法InvokeCommand()中return:如果你的扩展不能处理给定的动词,它应始终 return E_FAIL 以便 Windows 尝试 IContextMenu 的其他实现(有关详细信息,请参阅 Microsoft documentation)。似乎当单击高级用户菜单项时,Windows 首先调用了我的扩展名(* 文件类型),然后因为它没有 return E_FAIL未知动词,Windows 认为我的 shell 扩展程序已经处理了这个事件,所以它没有通过名义上的高级用户菜单回调处理它。

顺便说一句,我觉得有三件事很奇怪:

  1. 为什么 Windows 甚至 尝试 处理这个具有 shell 文件扩展名的高级用户菜单事件?此菜单是否使用与任何其他资源管理器的文件上下文菜单相同的 design/mechanism 编码?

  2. 为什么这个错误还没有产生更多的副作用?我的意思是这应该从一开始就破坏了整个 shell 扩展系统,不是吗?

  3. 为什么这么多应用程序都有这个bug? (意思是为什么这么多应用程序没有按预期 return E_FAIL?)。我写这段代码已经有一段时间了,我真的不记得它是从哪里来的,但我猜它来自 Microsoft 示例或任何 Microsoft 员工教程(太面向 Microsoft,无法自己编写代码) .如果是这样的话,这可能会回答为什么这么多 shell 扩展会导致这个问题...

如果有人对此主题有一些想法可以分享,我会很感兴趣! 顺便说一句,希望我的post可以帮助到其他开发者。当看到新的 Microsoft 示例非常有用时,我首先害怕不得不从他们的示例中重写我的所有 shell 扩展,而不知道我的代码有什么问题!