我正在尝试编写一个shell扩展,将菜单项添加到所有文件类型的上下文菜单中。扩展程序的代码(完整地)位于here,但在我描述问题时,我将在下面列出一些相关部分。
ContextMenu
类实现IShellExtInit
和IContextMenu
接口:
class ContextMenu : public IShellExtInit, IContextMenu
{
public:
// [...]
// IShellExtInit methods
STDMETHODIMP Initialize(PCIDLIST_ABSOLUTE pidlFolder,
IDataObject *pdtobj, HKEY hkeyProgID);
// IContextMenu methods
STDMETHODIMP GetCommandString(UINT_PTR idCmd, UINT uType, UINT *pReserved,
LPSTR pszName, UINT cchMax);
STDMETHODIMP InvokeCommand(LPCMINVOKECOMMANDINFO pici);
STDMETHODIMP QueryContextMenu(HMENU hmenu, UINT indexMenu, UINT idCmdFirst,
UINT idCmdLast, UINT uFlags);
}
所有方法都使用MessageBox()
调用进行操作,以指示何时调用它们。只有一个小问题 - 它们从未被调用过。
扩展程序包含另一个实现IClassFactory
的类。 IClassFactory::CreateInstance()
的实施如下:
STDMETHODIMP ClassFactory::CreateInstance(IUnknown *pUnkOuter, REFIID riid,
LPVOID *ppvObject)
{
if (pUnkOuter) {
return CLASS_E_NOAGGREGATION;
}
if (!ppvObject) {
return E_INVALIDARG;
}
*ppvObject = NULL;
ContextMenu *contextMenu = new ContextMenu;
HRESULT hResult = contextMenu->QueryInterface(riid, ppvObject);
contextMenu->Release();
return hResult;
}
我可以确认是否正在调用此方法,我还可以确认,ContextMenu::QueryInterface()
在riid
被设置为IID_IContextMenu
的情况下被调用。
然而,之后没有任何事情发生。没有调用IContextMenu
方法。 IShellExtInit::Initialize()
也不是。DllRegisterServer()
。为什么会这样?
编辑:我完全忘了描述扩展程序的注册方式。 Logstash函数创建以下注册表项/值并检查错误代码以确认它们已创建:
HKCR\CLSID\{CLSID}
,价值 NULL
,数据: NitroShellExt
HKCR\CLSID\{CLSID}\InprocServer32
,价值 NULL
,数据: [path to DLL]
HKCR\CLSID\{CLSID}\InprocServer32
,价值 ThreadingModel
,数据: Apartment
HKCR\*\ShellEx\ContextMenuHandlers\NitroShellExt
,价值 NULL
,数据: {CLSID}
HKLM\Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved
,价值 {CLSID}
,数据: NitroShare Context Menu
...其中{CLSID}
是{52A10783-C811-4C45-9A3D-221A962C8640}
。然后我使用regsvr32
注册扩展名和regedit
以确认密钥/值确实存在。