无法使用Explorer中显示的IShellFolder :: EnumObjects枚举RecentPlaces.lnk下的项目

时间:2014-03-25 11:29:33

标签: winapi visual-c++ explorer windows-shell

我在查找并获取资源管理器显示的“最近的位置”下的所有项目时遇到问题。 我试过:

  1. 我获取“最近的地方”的所有链接(“收藏夹”)的路径,它是“C:\ Users \\ Links \ RecentPlaces.lnk”。
  2. SHCreateItemFromParsingName获取IShellItem
  3. 检查它是否是链接IShellItem :: GetAttributes并检查SFGAO_LINK  对于Link,我将目标ShellItem作为:  IShellItem :: BindToHandler传递BHID_LinkTargetItem。
  4. 使用IShellItem :: BindToHandler传递BHID_SFObject来从IShellItem获取IShellFolder
  5. 枚举IShellFolder shellFolder-> EnumObjects(NULL,SHCONTF_FOLDERS | SHCONTF_NONFOLDERS,& enumIDList) enumIDList-> Next(1,& childItemID,NULL)<<这里它仅在第一次迭代中返回S_FALSE。 我可以使用相同的方法枚举所有其他shellItems(所有库,计算机,其他链接,如桌面,下载等)。 但是“最近的地方”链接失败了。 请在这里建议我做错了什么。或任何其他应该起作用的方法。 在此先感谢。
  6. 编辑:

    HRESULT hr;
    C_ComPtr<IShellItem> shellItem;
    hr = SHCreateItemFromParsingName(TEXT("C:\Users\srvdsk\Links\RecentPlaces.lnk"), NULL, IID_PPV_ARGS(&shellItem));
    if(S_OK != hr) return;
    SFGAOF attrib;
    shellItem->GetAttributes(SFGAO_FOLDER | SFGAO_LINK, &attrib);
    if ( (attrib&SFGAO_LINK) ) {
    
        C_ComPtr<IShellItem> linkTargetShellItem;
        hr = shellItem->BindToHandler(NULL, BHID_LinkTargetItem, IID_PPV_ARGS(&linkTargetShellItem));
        if (S_OK != hr) return;
    
        linkTargetShellItem->GetAttributes(SFGAO_FOLDER | SFGAO_LINK, &attrib);
        if ( (attrib&SFGAO_FOLDER) ) {        
            C_ComPtr<IShellFolder> shellFolder;
            hr = linkTargetShellItem->BindToHandler(NULL, BHID_SFObject, IID_PPV_ARGS(&shellFolder));
            if (S_OK != hr) return;
    
    
            C_ComPtr<IEnumIDList> enumIDList;
            SHCONTF const flags = SHCONTF_FOLDERS | SHCONTF_NONFOLDERS;
            hr = shellFolder->EnumObjects(NULL, flags, &enumIDList);
            if (S_OK != hr) return;
    
            LPITEMIDLIST childItemID = NULL;
            while (S_OK == enumIDList->Next(1, &childItemID, NULL)) { //Next is returning S_FALSE in first iteration itself
    
                STRRET strRetItemName;
                hr = shellFolder->GetDisplayNameOf(childItemID, SHGDN_FORPARSING, &strRetItemName);
                if (S_OK != hr) return;            
            }
        }    
    }
    

2 个答案:

答案 0 :(得分:0)

在这个地方你可以获得linkTargetShellItem:

shellItem->BindToHandler(NULL, BHID_LinkTargetItem, IID_PPV_ARGS(&linkTargetShellItem));

但是在这个地方你使用旧的shellItem:

shellItem->BindToHandler(NULL, BHID_SFObject, IID_PPV_ARGS(&shellFolder));

你应该linkTargetShellItem而不是shellItem。

替代算法:

procedure IterateLinkTarget(const AFileName: UnicodeString);
var
  ShellLink: IShellLinkW;
  PersistFile: IPersistFile;
  IDList: PItemIDList;
  Desktop: IShellFolder;
  Folder: IShellFolder;
  Enum: IEnumIDList;
  Child: PItemIDList;
  Fetched: DWORD;
begin
  OleCheck(CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IShellLinkW, ShellLink));
  try
    OleCheck(ShellLink.QueryInterface(IPersistFile, PersistFile));
    try
      OleCheck(PersistFile.Load(PWideChar(AFileName), STGM_READ));
      OleCheck(ShellLink.GetIDList(IDList));
      try
        OleCheck(SHGetDesktopFolder(Desktop));
        try
          OleCheck(Desktop.BindToObject(IDList, nil, IShellFolder, Folder));
          try
            OleCheck(Folder.EnumObjects(0, SHCONTF_FOLDERS or SHCONTF_NONFOLDERS, Enum));
            while Enum.Next(1, Child, Fetched) = S_OK do
              try

                // Process child here

              finally
                CoTaskMemFree(Child);
              end;
          finally
            Folder := nil;
          end;
        finally
          Desktop := nil;
        end;
      finally
        CoTaskMemFree(IDList);
      end;
    finally
      PersistFile := nil;
    end;
  finally
    ShellLink := nil;
  end;
end;

答案 1 :(得分:0)

我花了很多年时间试图解决这个问题,并最终发现我的问题是CoInitializeEx(COINIT_MULTITHREADED)。最近的items文件夹仅适用于COINIT_APARTMENTTHREADED。请参阅此link