ShellAnything icon indicating copy to clipboard operation
ShellAnything copied to clipboard

Right-click on a directory with Windows Explorer in the left panel shows the menus twice

Open end2endzone opened this issue 6 years ago • 3 comments

end2endzone avatar May 03 '19 19:05 end2endzone

image

end2endzone avatar May 03 '19 19:05 end2endzone

I am unable to identify the cause of the issue. Anyone here can help?

end2endzone avatar Jun 12 '19 17:06 end2endzone

The issue is still occurring in 0.9.0, branch feature-issue115, 22d3d87b4ec1c733d6990c3d5ed13061a18e0ed4.

end2endzone avatar Jan 04 '24 12:01 end2endzone

Hint: Implement a ScopeLogger class in file LoggerHelper.h which job is to log (or vebose log) when the code enters/leave a scope. This will be much useful when trying to debug this issue.

EDIT: done : ScopeLogger.

end2endzone avatar Aug 16 '24 16:08 end2endzone

I am uncertain why this is happening. Here are two log captures of the same use case : a user right-click on directory C:\Windows\Cursors" :

  1. right-panel.txt made by right-clicking on directory from the right-panel side (file list view).
  2. left-panel.txt made by right-clicking on directory from the left-panel side (directory tree view).

(both files were sanitized. See where I inserted ... for parts that were removed)


Investigations notes:

  • In left log, 2 instances of CContextMenu are created. This is why we see ShellAnything menus rendered twice in the Context Menu.

    • The second instance is created and destroyed while the first instance is "in use".
    • The first pass assigns a unique set of command ids to ShellAnything menus. The second instance reassign completely different command ids to ShellAnything menus (same instances). This overrides the previous command ids that were sets previously. When the system calls CContextMenu::GetCommandString() with the previous command ids, this creates tons of errors. For example : E0824 17:46:38.655484 22964 CContextMenu.cpp:515] CContextMenu::GetCommandString(), unknown menu for command_id=1. QueryContextMenu() ended with m_FirstCommandId=143, target_command_id=144. See #31 for details.
  • Flags sent to QueryContextMenu() in both log files are different.

    1. left-panel: flags=0x00000414=(CMF_EXPLORE|CMF_CANRENAME|CMF_ASYNCVERBSTATE)
    2. right-panel: flags=0x00020494=(CMF_EXPLORE|CMF_CANRENAME|CMF_ITEMMENU|CMF_ASYNCVERBSTATE)
    3. CMF_ITEMMENU is specified for right-panel. CMF_ITEMMENU means : 0x00000080. The calling application is invoking a shortcut menu on an item in the view (as opposed to the background of the view).
  • The shell extension is registering itself for multiple types : *, Directory, Directory/Background, Folder, and Drive. Registering the shell extension for AllFilesystemObjects is also discussed in #120. Maybe registering itself for multiple type is the reason why Windows File Explorer creates 2 instances of CContextMenu?

end2endzone avatar Aug 25 '24 13:08 end2endzone

The code has already been protected with a cheap patch for detecting calling CContextMenu::QueryContextMenu() twice for the same HMENU.

The fix requires the field CContextMenu::m_previousMenu to be declared static. It was implemented as such in v0.7.0. However, somewhere between v0.7.0 and v0.8.0, the fix was dropped during refactoring.

end2endzone avatar Aug 25 '24 15:08 end2endzone