Sure, we do that: Context menu edition


A customer reported a problem that occurred only when they installed a particular application. If they uninstalled it, then the problem went away. After installing the application, the "Run As" context menu option stopped working. The customer didn't provide any other details, but we were able to make an educated guess as to what was going on.

A common programming error in context menu extensions occurs in extensions which add only one menu item. These extensions ignore the parameters to the IContextMenu::InvokeCommand and simply assume that the only reason the method can be called is if the user selected their menu item. After all, if you have only one invokable item, there's no need to figure out which one the user selected, because you have only one to begin with!

The problem is that a context menu extension can be invoked not because the user selected an item under its control but because a verb is being invoked programmatically, and each handler is being asked, "Do you know how to do this?"

The result is that the context menu host calls the extension to say, "If you know how to do runas, then please do so," and the the extension says "Sure, we do that" and starts doing its thing. If you are unlucky and the grabby extension is asked the question before the actual runas extension, the runas command winds up being hijacked by the grabby extension.

(This is the same mistake that causes the Copy To and Move To commands to behave strangely if you add them to the context menu: They assume that the only reason they are invoked is that the user invoked their command, because they weren't designed to be hosted by context menus to begin with! They were designed to go into the toolbar, and the toolbar hosting code never invoked commands by name. It's like taking a ladder and using it as a bridge between two tall buildings. Sure, you can now cross from one building to another, but you also run a serious risk of falling to your death.)

A variation on the initial problem is "I found that after installing a particular program, I can't run anything from the Start menu." I know of at least two programs which install context menu extensions which steal the "open" command on executables.

This problem is sufficiently prevalent that there is a special compatibility flag that can be set on a shell extension to say, "This is a grabby shell extension that steals commands. Never ask it if it supports anything, because it will always say yes!"

Notice that the "MoveTo CopyTo Context Menu" is on the list, which I find interesting because MoveTo/CopyTo was never meant to go on the context menu in the first place. Going back to our analogy, it'd be as if the ladder company issued a safety bulletin to warn people of problems that can occur if you use it as a bridge between two tall buildings!

Comments (17)
  1. Joshua Ganes says:

    If the ladder company was repeatedly involved in lawsuits from people who were injured by using them as bridges, you can be sure that the warning would start popping up on all new ladders. It would always be present like "Caution: Hot" on coffee cups.

    I like the term "grabby extension". Is that a rigorously-defined technical term?

  2. Gabe says:

    I find it hard to imagine how a bug that causes "I can't run anything from the Start menu" to last more than a day or two on the developer's machine before they attempt to investigate the problem and try to fix it. One can only assume that the developers just think their Start menus are inexplicably broken and ship the software anyway!

  3. Justin says:

    Presumably the software was developed and tested on a version of Windows before explorer started using IContextMenu::InvokeCommand in this way.

  4. No One says:

    @Gabe: Or the developers and testers both only use desktop shortcuts.

  5. Cesar says:

    Or the developer is one of those people who use desktop icons or quick launch icons to run all the software they use (plus Win-E and "Win-R cmd Enter" for the file manager and the shell).

  6. Joshua says:

    I bet the compat flag was added for CopyTo and MoveTo because people kept putting them in context menus. It sort of makes sense.

    @Cesar: Or they're shell isn't explorer. It happens.

  7. alegr1 says:

    THis is where the blacklist should be useful.

  8. Kimmo says:

    Ray, glad that you're still around (b)(p)(i)tching <– in a good way. Thanks /k

  9. Raphael says:

    Hmm, I wonder if that is why the shell extension of a popular image viewer crashes my explorer when invoked from a search result view …

  10. Anonymous Coward says:

    Not to sound grumpy, but if the way verbs work turns out to be different depending on whether it's invoked from the context menu, programmatically, or from the toolbar, you should take the design of the system back to the drawing board.

    [Verbs invoked by context menu and programmatically are supposed to be the same. Toolbar is totally unrelated. -Raymond]
  11. xpclient says:

    Well on Windows 8, Copy To and Move To are part of the Command Store (and Ribbon) so they can be added to context menu with this tweak and so far I haven't noticed any side effects:

    Windows Registry Editor Version 5.00

    [HKEY_CLASSES_ROOT*shellWindows.CopyToMenu]

    "ExplorerCommandHandler"="{3852C2E2-4A16-4b11-8E71-F8904C37EC3D}"

    "CommandStateSync"=""

    "Icon"="imageres.dll,-5304"

    [HKEY_CLASSES_ROOT*shellWindows.MoveToMenu]

    "ExplorerCommandHandler"="{F60C3E02-214A-462b-9B07-56EA38545A13}"

    "CommandStateSync"=""

    "Icon"="imageres.dll,-5303"%

  12. Anonymous Coward says:

    Raymond, next time read a post before replying to it.

    I hate to draw this out, because it will be a bore to other readers, but since you apparently have issues with text comprehension, here goes:

    Verbs invoked by context menu and programmatically are supposed to be the same, but they aren't. That's what the article is about, and this is a severe shortcoming in the design of the whole system.

    Toolbar items are completely unrelated, but that again is part of the problem. It's a flaw that shows that people didn't think the design through properly.

    If the system had been designed properly (and this isn't deep stuff, so there is no excuse for getting it wrong) the whole problem the article describes wouldn't exist. Someone who can look at IContextMenu and not cringe should be banned from programming.

    [But why should toolbar buttons and context menus share the same execution model? How would you like to create an IContextMenu for every button on your toolbar? (And you forget that the toolbar thing was purely internal to Explorer; it's not part of any public interface. Explorer thought it would be clever and unify toolbar buttons and context menus for the purpose of its toolbar, and look what happened.) And how would you unify command-based invoke and menu-based invoke? It seems you're trying to unify two things that have no common ground. (In one case, you have a string and no menu. In the other case, you have a menu and no string.) -Raymond]
  13. DumpCOM.now says:

    I blame this on COM. Unfortunately it's even more obfuscated in windows.next

  14. Anonymous Coward says:

    @DumpCOM.now: This has nothing to do with COM; it's caused by a poor interface specification. You would have gotten the exact same problem if you let the same blockhead design an interface for use with Java, DCOP, D-Bus, or anything else.

    @Raymond: You're starting to rave irrationally. Just stop defending the indefensible, you'll feel better. [Note: most readers can probably skip the rest of this post, it's just tearing Raymond's reply apart, but if you read it, chances are I won't write anything you haven't already thought.]

    @But…: Because there's no reason toolbar buttons that act on an object couldn't be put in the context menu instead, so a well designed system will be agnostic from where the action is performed.

    @How…: Toolbar buttons that don't act on objects weren't under discussion, you know that.

    @(And…): It went wrong because the ill-designed system caused different behaviour when not used from the toolbar. And of course because whoever wrote the MoveTo and CopyTo implementation (and the broken context menu extensions) can't read documentation, but that just shows that it's easier to get the implementation wrong than right, and that you won't notice that you did it wrong, at least when /you/ test it.

    @And…: You should be ashamed to even ask this. Menus and such shouldn't even come into play at this point, rather extension writers should implement actions to perform on objects. (Let's call them verbs to stick with current terminology.) No implementer should have to care from where it was invoked.

    @It…: No common ground? [expletive deleted] What about the thing that actually needs to be done?

    @(In…): As already stated, that doesn't matter in a well-designed system.

    [The people who wrote the toolbar said, "Hey, instead of inventing a whole new interface, let me reuse this existing one. This is just an internal thing (not documented or third-party extensible), so no need to get all fancy." I can't see which side of the fence you're arguing, whether it was a good idea to unify toolbar, verbs, and context menus, or that it was a bad idea. Personally, I wouldn't have unified them, because well you can see what went wrong when they were unified. -Raymond]
  15. James says:

    Is there a simialr issue that would cause drag-and-drop to stop working?  If so, how do you find the fautly app?

  16. Joshua says:

    […"Hey, instead of inventing a whole new interface, let me reuse this existing one. This is just an internal thing (not documented or third-party extensible), so no need to get all fancy." …]

    My interpretation of that would be COM interfaces are too heavyweight by the time this starts to sound like a good idea.

  17. Anonymous Coward says:

    Raymond, the reason you can't see what I'm arguing is that you don't actually read what I type. The answer to your question is in my previous posts, and I also disagree that the toolbar people caused the root of mess (unless the same coincidentally also designed the architecture of the verb system), and I've explained why in previous posts.

    Joshua, COM interfaces aren't heavyweight (they're just vtables really) and as I wrote above, unifying toolbar buttons that act on objects and context menu items is a good thing. The problems are caused by bad interface design.

    [When you say that something is bad you have to say what would be better. All you're saying is "they should be unified" but I have not seen a concrete proposal as to how it should be done. (Because it was done, but apparently not to your satisfaction.) -Raymond]

Comments are closed.

Skip to main content