【问题标题】:Windows 7 - Shell Extension dll Initialize method called twice on explorer left paneWindows 7 - 在资源管理器左窗格中调用两次 Shell 扩展 dll 初始化方法
【发布时间】:2012-03-27 15:48:38
【问题描述】:

我有一个 c++ shell 扩展 dll。 Initialize 方法被调用两次,如果我单击资源管理器窗口左窗格树视图文件夹。但是如果我点击资源管理器窗口右窗格中的任何文件夹,Initialize 方法就会调用一次。

问题是我新添加的菜单项在上下文菜单中显示两次,如果我单击左窗格树视图。

我想知道,它是一个窗口功能吗? 我已经评论了我的所有实现并使用以下代码进行了测试:

IFACEMETHODIMP CMyContextMenu::QueryContextMenu(HMENU hmenu, UINT /*uIndex*/, UINT    cmdFirst, UINT /*uidCmdLast*/, UINT /*uFlags*/ )
{
UINT cmdId = uidCmdFirst;
OutputDebugString(L"QueryContextMenu");

    return MAKE_HRESULT ( SEVERITY_SUCCESS, FACILITY_NULL,  cmdId  - mdFirst );
}


IFACEMETHODIMP CMyContextMenu::Initialize(LPCITEMIDLIST pidlFolder, LPDATAOBJECT  pDO, HKEY /*hkeyProgID*/)
{
OutputDebugString(L"Initialize");
return S_OK;
}

当我单击左窗格时,DebugViewr 输出为:

初始化

查询上下文菜单

初始化

查询上下文菜单

NoRemove Directory
{
    NoRemove Background
    {
        NoRemove ShellEx
        {
            NoRemove ContextMenuHandlers
            {
                ForceRemove myContext = s '{AE843198-3C5D-4EA6-B74F-7A41FC91D7FF}'
            }
        }
    }
}

NoRemove Directory
{
    NoRemove ShellEx
    {
        NoRemove ContextMenuHandlers
        {
            ForceRemove myContext = s '{AE843198-3C5D-4EA6-B74F-7A41FC91D7FF}'
        }
    }
}

以上注册表项在 Win 7 中导致此问题,如果我删除“NoRemove Background”,上下文菜单将在树视图中显示一次。但是如果我点击文件夹空白区域 Initialize 方法将不会被调用。

【问题讨论】:

  • 我想您说的是上下文菜单外壳扩展。如果是这样,它肯定不是正确的 Windows 功能。可以发一些代码吗?
  • 初始化(LPCITEMIDLIST pidlFolder,LPDATAOBJECT pDO,HKEY /*hkeyProgID*/)。我正在用这种方法做我的菜单填充。我在这个函数中添加了日志消息,它看起来像调用了两次初始化方法。
  • 能否请您发布代码,而不仅仅是签名?否则就是猜谜游戏。
  • Flot2011 - 我添加了我的实际代码。谢谢
  • 你在另一个系统上试过这个吗?这不是一个直接的问题。还有另一个对象,例如另一个 shell 扩展,可能会导致二次初始化/枚举。

标签: c++ windows winapi windows-shell


【解决方案1】:

我从我的真实程序中发布了一个工作示例(为清楚起见,省略了特定于应用程序的代码)。请尝试一下。

STDMETHODIMP CShlExtExample::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 ) ))
   {
       // Return an "invalid argument" error.
       return E_INVALIDARG;
   }

   // Get a pointer to the actual data.
   hDrop = (HDROP) GlobalLock ( stg.hGlobal ); 
   if ( NULL == hDrop )
       return E_INVALIDARG;

   // Make sure there is at least one file to show menu for.
   UINT uNumFiles = DragQueryFile ( hDrop, 0xFFFFFFFF, NULL, 0 );
   HRESULT hr = S_OK;  
   if ( 0 == uNumFiles )
   {
       GlobalUnlock ( stg.hGlobal );
       ReleaseStgMedium ( &stg );
       return E_INVALIDARG;
   }

   // Application specific code.

   GlobalUnlock ( stg.hGlobal );
   ReleaseStgMedium ( &stg );

   return hr;

}

   STDMETHODIMP CShlExtExample::QueryContextMenu (
   HMENU hmenu, UINT uMenuIndex, UINT uidFirstCmd,
   UINT uidLastCmd, UINT uFlags )
   {
     // If the flags include CMF_DEFAULTONLY then do nothing.
     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 );
   }

【讨论】:

  • 我已经实现了你的代码,Initialize 方法被调用了两次。但 QueryContextMenu 从未调用过
  • 此问题仅在 Windows 7 中发生
猜你喜欢
  • 2011-08-27
  • 1970-01-01
  • 1970-01-01
  • 2013-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多