Windows 7 - folder background context-menu extesion disables 'create new folder' button

Asked By arloan
15-Dec-09 09:28 AM
Hi all,

I created a very simple shell extension using vc6, implemented IShellExtInit
& IContextMenu interfaces to provide a 'hello' context menu item for
directory background, which shows up a message box with 'hello world!'. It
works perfectly, but I found that it disabled the 'Create New Folder' button
on the toolbar of the shell open/save dialog box. In fact, when  I hit the
'Create New Folder' button, the shell calls my extension's
IContextMenu::InvokeCommand() method. Am I doing anything wrong? Thanks for
anybody's help.

The whole project can be download at here:
http://cid-0475c87002affa39.skydrive.live.com/self.aspx/temp/testext.zip

Below is the most significant codes:

// IContextMenu
STDMETHODIMP Cshmenu::QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT
idCmdFirst, UINT idCmdLast, UINT uFlags)
{
if (uFlags & CMF_DEFAULTONLY)
{
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, USHORT(0));
}

InsertMenu(hmenu, indexMenu++, MF_BYPOSITION | MF_STRING, idCmdFirst,
_T("&Hello, world!"));
return MAKE_HRESULT(SEVERITY_SUCCESS, 0, 1);
}

STDMETHODIMP Cshmenu::GetCommandString(UINT_PTR idCmd, UINT uFlags, UINT *
pwReserved, LPSTR pszName, UINT cchMax)
{
switch (uFlags)
{
case GCS_HELPTEXTW:
lstrcpyW((LPWSTR)pszName, L"HelloW!");
break;
case GCS_HELPTEXTA:
lstrcpyA(pszName, "HelloA!");
break;
case GCS_VERBW:
lstrcpyW((LPWSTR)pszName, L"test_hello");
break;
case GCS_VERBA:
lstrcpyA(pszName, "test_hello");
break;
}

return S_OK;
}

STDMETHODIMP Cshmenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
{
LPCMINVOKECOMMANDINFOEX exinfo = (LPCMINVOKECOMMANDINFOEX)pici;

if (HIWORD(exinfo->lpVerbW))
{
MessageBox(pici->hwnd, _T("Hello, world!"), _T("helloW"),
MB_ICONINFORMATION);
}
else
{
MessageBox(pici->hwnd, _T("Hello, world!"), _T("helloA"),
MB_ICONINFORMATION);
}

return S_OK;
}
IShellExtInit
(1)
QueryContextMenu
(1)
IContextMenu
(1)
InvokeCommand
(1)
ViewDetails
(1)
InsertMenu
(1)
IdCmdFirst
(1)
IdCmdLast
(1)
  bviksoe replied to arloan
16-Dec-09 11:28 AM
nit
t
ton
the
or
drive.live.com/self.aspx/temp/testext.zip
*

Does it matter if you actually filter on idCmd in GetCommandString() ?
It looks like you could be returning data and S_OK for a lot of things
that you really should not.

bjarke
  Jim Barry replied to arloan
16-Dec-09 05:09 AM
Yes - you mustn't respond to InvokeCommand unless you recognise the
command as one of your own. In all other cases you must ignore the call
and return a failure code such as E_FAIL.

- Jim
  arloan replied to bviksoe
16-Dec-09 06:52 AM
According to my understanding, the shell should not call my extension's
GetCommandString() if the idCmd is not belong to my extension registered
during QueryContextMenu(), of which the return value should play it is role.

I tried to filter the idCmd in GetCommandString() according to your
suggestion, but it does not work still. Thanks a lot.

Arloan
  arloan replied to Jim Barry
16-Dec-09 07:01 AM
I modified InvokeCommand() and directly return E_FAIL, but the 'Create New
Folder' button still does not work.

STDMETHODIMP Cshmenu::InvokeCommand(LPCMINVOKECOMMANDINFO pici)
{
return E_FAIL;
}

I think that the shell just should not call my extension's InvokeCommand()
if the verb/id is not belong to my extension registered during
QueryContextMenu() on it is return value.

Thanks.
  Jim Barry replied to arloan
16-Dec-09 08:11 AM
Then I am not sure what else to suggest - it works for me. Are there any
other background context menu handlers registered?


The issue is that the file dialog wants to invoke the "NewFolder"
command on a composite context menu. The composite menu does not know
which of its contained menu handlers implements the command so it calls
each of them in turn until one succeeds. Yes the composite menu could
query the verb of every single menu item until it finds one that
matches, but it would be less efficient.

- Jim
  arloan replied to Jim Barry
17-Dec-09 05:32 AM
There is no other background handlers registered. I tested my extension in a
fresh installed windows 2000 in vmware, the same prolem's still there. This
is really weired. :-(
project, or my project supplied in previous message works in your system?
Thanks.


Yes, I found the shell calls my extension with ver 'NewFolder', and I have
been thought that the shell goes wrong somewhere. If the shell behaves like
that u've figured out, that is just reasonable. Would you be so nice to tell
me where to find the official or unofficial tech-info about this behavour?
Thank u so much for your patient.

Arloan. P
  arloan replied to Jim Barry
17-Dec-09 05:59 AM
Hi, it works now! I reinstalled my build system & test system, and it works
perfectly.
Maybe one of the systems is polluted by other 3rd-party shell extensions
which out of my mind. Thank you very much for your suggestion & patient!!

PS. I still want to learn about that is there any further
official/unofficeal techinfo about how the shell handles the
'NewFolder'(and/or other standard verbs) verb, would you please tell me
about that? Thanks a lot.
  Jim Barry replied to arloan
17-Dec-09 11:54 AM
You're welcome.


Not sure what there is to tell... the verbs "NewFolder", "ViewDetails"
and "ViewList" are mentioned in the CMINVOKECOMMANDINFOEX documentation.
However, "ViewDetails" and "ViewList" fell out of use in Windows 2000,
when the file dialog's "List" and "Details" buttons were replaced by a
drop-down menu button. The file dialog implements the "Create New
Folder" command by invoking the "NewFolder" command on the folder's
background context menu object. This context menu is a composite menu
consisting of a hardwired menu merged with the context menu handlers
registered under the Directory\Background subkey.

- Jim
help
in the folder) I follow all the recommended steps ie: 1. CoCreateInstance and ask for IContextMenu 2. IShellExtInit::Initialize passing the pidl of the folder in question 3. QueryContextMenu to fill the menu items 4. (optional) Query the object for IID_IObjectWithSite and pass it channel all WM_INITMENUPOPUP etc, but when I finally try to create the requested item with IContextMenu::InvokeCommand, it returns E_FAIL (GetLastError is 87) This is the same whether I do step zabkat.com Platform SDK Shell Discussions Vista (1) XP (1) Windows Server (1) CLSID_NewMenu (1) IContextMenu (1) KmGeFMEJZLMotTEkQhkayBnyIznhAZZiTkc (1) SHFileOperation (1) INewMenuClient (1) Hi nikos, From the documentation you mentioned: Note considered as end-user feature". Personally, I think the workaround using the folder's background IContextMenu should work for your purpose. The menu doesn't have to be shown before invoking it public. Sorry. From the information I've got so far, I think using the IContextMenu to invoke shellnew command on Vista will be the only way. Regards, Walter Wang (wawang
571077DC-. . .-4DE4B7EFC4E3} = s 'CtxCreateHash Class' . . . Platform SDK Shell Discussions XP (1) Vista (1) UINT (1) IContextMenu (1) LPCMINVOKECOMMANDINFO (1) ContextMenuHandlers (1) InvokeCommand (1) HKEY_CLASSES_ROOT (1) Hi All, A fresh build using the problem: Create 2 different menu Dlls which do nothing other than implements the minimum: * IShellExtInit::Initialize(LPCITEMIDLIST, LPDATAOBJECT, HKEY); * IContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO); * IContextMenu::GetCommandString(UINT, UINT, UINT*, LPSTR, UINT); * IContextMenu::QueryContextMenu(HMENU, UINT, UINT, UINT, UINT); InsertMenu always return TRUE, and GetLastError() always returns ERROR_SUCCESS. Only
IContextMenu with a shortcut and another file / folder selected Windows 7 Hi, I have a shell that's giving inconsistent results if both a shortcut and a file are selected. In IShellExtInit.Initialize I render the IDataObject to a CF_HDROP and use DragQueryFile to get the paths get two paths in this case? Thanks, Craig Peterson Scooter Software Platform SDK Shell Discussions IContextMenu.QueryContextMenu (1) IShellExtInit.Initialize (1) Vista (1) XP (1) HKeyProgID (1) ContextMenuHandlers (1) QueryContextMenu (1) DragQueryFile (1) Hi Craig, It appears to be what Explorer does! I have noticed both a file and a shortcut (lnk) are selected in windows explorer, our shell extension IShellExtInit.Initialize only gets the shortcut's name if the focus rect is on the shortcut consistently, but it's actually creating two copies of my object now, and calling Initialize / QueryContextMenu on both of them, resulting in multiple menu items. The first Initialize call is always
CompilerServices Imports Microsoft.Win32 Imports System.Security.Permissions Imports System.Drawing Public Class CtxMenu Implements IShellExtInit Implements IContextMenu ' * ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ' IContextMenu Protected m_dataObject As IDataObject = Nothing Private m_hDrop As Integer = 0 Public Shared Function Main(ByVal Show(("An exception was thrown : " + e.Message)) Return 1 End Try End Function Public Function QueryContextMenu(ByVal hMenu As IntPtr, _ ByVal iMenu As Integer, _ ByVal idCmdFirst As Integer, _ ByVal idCmdLast As Integer, _ ByVal uFlags As QueryContextMenuFlags) As Integer Implements IContextMenu.QueryContextMenu Try Dim id As Integer = 1 If (((uFlags And (QueryContextMenuFlags.CMF_VERBSONLY Or (QueryContextMenuFlags.CMF_DEFAULTONLY Or id + 1), "Cinco") End If Return id Catch ex As Exception MessageBox.Show(ex.Message, "QueryContextMenu") End Try End Function Public Sub GetCommandString(ByVal idcmd As Integer, ByVal uflags As Integer ByVal reserved As Integer, ByVal commandstring As System.Text.StringBuilder, ByVal cch As Integer) Implements IContextMenu.GetCommandString Select Case (CType(uflags, GCS)) End Select End Sub ' invoke the command on the