我正在尝试使用c ++编写上下文菜单处理程序。我希望处理程序可以处理所有文件和所有文件夹,也可以处理资源管理器左窗格中的文件和文件夹。 我从一个CodeProject项目开始,该项目旨在适应我的需求。我是从here获得的。
直到现在,除了资源管理器左窗格中的文件夹之外,其他所有东西似乎都可以正常工作。 那里我得到一个AccessViolationException。在右键单击和上下文菜单的显示之间发生例外。 我删除了不同功能中的代码,直到再次起作用,看来问题出在QueryContextMenu方法上。
有人知道我在做什么错吗?
这是我当前有效的代码(因为没有添加任何项目,所以很明显):
STDMETHODIMP ShellExt::Initialize (LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hProgID )
{
FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
STGMEDIUM stg = { TYMED_HGLOBAL };
HDROP hDrop;
// Look for CF_HDROP data in the data object.
if ( FAILED( pDataObj->GetData ( &fmt, &stg ) ))
{
// Nope! Return an "invalid argument" error back to Explorer.
return E_INVALIDARG;
}
// Get a pointer to the actual data.
hDrop = (HDROP) GlobalLock ( stg.hGlobal );
// Make sure it worked.
if ( NULL == hDrop )
return E_INVALIDARG;
// Sanity check - make sure there is at least one filename.
UINT uNumFiles = DragQueryFile ( hDrop, 0xFFFFFFFF, NULL, 0 );
HRESULT hr = S_OK;
if ( 0 == uNumFiles )
{
GlobalUnlock ( stg.hGlobal );
ReleaseStgMedium ( &stg );
return E_INVALIDARG;
}
// Get the name of the first file and store it in our member variable m_szFile.
if ( 0 == DragQueryFile ( hDrop, 0, m_szFile, MAX_PATH ) )
hr = E_INVALIDARG;
GlobalUnlock ( stg.hGlobal );
ReleaseStgMedium ( &stg );
return hr;
}
STDMETHODIMP ShellExt::QueryContextMenu (HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags )
{
return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 );
}
STDMETHODIMP ShellExt::GetCommandString (UINT_PTR idCmd, UINT uFlags, UINT* pwReserved, LPSTR pszName, UINT cchMax)
{
return E_INVALIDARG;
}
STDMETHODIMP ShellExt::InvokeCommand (LPCMINVOKECOMMANDINFO pCmdInfo)
{
return S_OK;
}
但是现在,如果我在ShellExt :: QueryContextMenu中添加一项,则资源管理器的左窗格将引发异常,而右窗格中的文件和文件夹会很好地工作。 我尝试了在互联网上找到的以下两个版本,但都存在相同的问题:
STDMETHODIMP ShellExt::QueryContextMenu (HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags )
{
// If the flags include CMF_DEFAULTONLY then we shouldn't do anything.
if ( uFlags & CMF_DEFAULTONLY )
return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 );
InsertMenu ( hmenu, uMenuIndex, MF_BYPOSITION, uidFirstCmd, _T("Test Item") );
return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 1 );
}
和
STDMETHODIMP ShellExt::QueryContextMenu (HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd, UINT uidLastCmd, UINT uFlags )
{
// If the flags include CMF_DEFAULTONLY then we shouldn't do anything.
if ( uFlags & CMF_DEFAULTONLY )
return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL, 0 );
UINT uID = uidFirstCmd;
UINT pos = uMenuIndex;
MENUITEMINFO mii = { sizeof(mii) };
mii.fMask = MIIM_STRING | MIIM_FTYPE | MIIM_ID | MIIM_STATE;
mii.fType = MFT_STRING;
mii.dwTypeData = _T("Menu 1");
mii.fState = MFS_ENABLED;
mii.wID = uID++;
if (!InsertMenuItem(hmenu, pos++, TRUE, &mii))
{
return HRESULT_FROM_WIN32(GetLastError());
}
return MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_NULL, uID - uidFirstCmd);
}
我在QueryContextMenu中得到的参数:
-hmenu = 0x0000000001480405
-uMenuIndex = 3
-uidFirstCmd = 148
-uidLastCmd = 32762
-uFlags = 1044
异常详细信息。
QueryContextMenu和GetCommandString中的代码被执行。异常发生在此之后但仍在上下文菜单可见之前。不幸的是,细节对我而言并不重要:
在explorer.exe中的0x00007FF9B1C4C613(shell32.dll)引发异常:0xC0000005:访问冲突读取位置0x00007FF9776D9868。发生
Stacktrace:
shell32.dll!00007ff9b1c4c613()
ExplorerFrame.dll!00007ff98d24993a()
ExplorerFrame.dll!00007ff98d2c69a4()
ExplorerFrame.dll!00007ff98d24de6c()
ExplorerFrame.dll!00007ff98d251286()
ExplorerFrame.dll!00007ff98d1fbad0()
ExplorerFrame.dll!00007ff98d1ad5b3()
ExplorerFrame.dll!00007ff98d180f2e()
user32.dll!00007ff9b079ca66()
user32.dll!00007ff9b079c34b()
comctl32.dll!00007ff99d78b0da()
comctl32.dll!00007ff99d78b017()
ExplorerFrame.dll!00007ff98d187521()
ExplorerFrame.dll!00007ff98d17d2e0()
comctl32.dll!00007ff99d78b0da()
comctl32.dll!00007ff99d78aef2()
user32.dll!00007ff9b079ca66()
user32.dll!00007ff9b079c34b()
duser.dll!00007ff98106dff5()
atlthunk.dll!00007ff983061208()
user32.dll!00007ff9b079ca66()
user32.dll!00007ff9b079c78c()
user32.dll!00007ff9b07afa83()
ntdll.dll!00007ff9b34833a4()
win32u.dll!00007ff9b0071184()
user32.dll!00007ff9b079bfbe()
user32.dll!00007ff9b079be38()
comctl32.dll!00007ff99d77a099()
comctl32.dll!00007ff99d80b556()
comctl32.dll!00007ff99d7b1302()
user32.dll!00007ff9b079ca66()
user32.dll!00007ff9b079c34b()
comctl32.dll!00007ff99d78b0da()
comctl32.dll!00007ff99d78b017()
ExplorerFrame.dll!00007ff98d1bf33b()
ExplorerFrame.dll!00007ff98d1bf27b()
comctl32.dll!00007ff99d78b0da()
comctl32.dll!00007ff99d78aef2()
user32.dll!00007ff9b079ca66()
user32.dll!00007ff9b079c582()
ExplorerFrame.dll!00007ff98d1748a3()
ExplorerFrame.dll!00007ff98d1747a9()
ExplorerFrame.dll!00007ff98d1746f6()
ExplorerFrame.dll!00007ff98d175a12()
ExplorerFrame.dll!00007ff98d1870c2()
windows.storage.dll!00007ff9af8db38c()
windows.storage.dll!00007ff9af8db045()
windows.storage.dll!00007ff9af8daf25()
SHCore.dll!00007ff9b164c315()
kernel32.dll!00007ff9b06281f4()
ntdll.dll!00007ff9b344a251()
答案 0 :(得分:0)
看来我已经解决了问题。我重新设计了该项目的其余部分,即IClassFactory的实现以及shellextension类的IUnknown接口的实现,目的是了解这些“内容”在该项目中的用途。
这样做的时候,我发现了一些Bug,未初始化的变量,转换为错误的类型等。我还将一些计数器从UINT更改为LONG,以便可以使用InterlockedIncrement而不是++。之后,问题似乎消失了。我不能确切地说出是什么错误导致了AccessViolationException,但是最后它并没有出现在我所认为的QueryContextMenu方法中...