最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - Get file path in shell extension - Stack Overflow

programmeradmin7浏览0评论

I have a shell extension that implements a context menu for text files. In the shell extension, I need to determine the path of the file for which this context menu was called.

For this, I decided to use IShellExtInit::Initialize, in which I call the SHGetPathFromIDList function to get the path to the file. However, the SHGetPathFromIDList function always returns FALSE and I cannot get the path to the file.

How can I get the path to the file in IShellExtInit::Initialize for which the context menu was called? The current implementation of IShellExtInit::Initialize looks like this:

// IShellExtInit
HRESULT Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID)
{

    std::wstring result;

    TCHAR path[MAX_PATH];

    if (SHGetPathFromIDList(pidlFolder, path)) {
        result += L"Path: "+ std::wstring(path) + L" \n ";
    }
    else {
        result += L"Failed to get path: ";
    }

    MessageBox(NULL, result.c_str(), L"", 0);

    return S_OK;
}

I have a shell extension that implements a context menu for text files. In the shell extension, I need to determine the path of the file for which this context menu was called.

For this, I decided to use IShellExtInit::Initialize, in which I call the SHGetPathFromIDList function to get the path to the file. However, the SHGetPathFromIDList function always returns FALSE and I cannot get the path to the file.

How can I get the path to the file in IShellExtInit::Initialize for which the context menu was called? The current implementation of IShellExtInit::Initialize looks like this:

// IShellExtInit
HRESULT Initialize(PCIDLIST_ABSOLUTE pidlFolder, IDataObject* pdtobj, HKEY hkeyProgID)
{

    std::wstring result;

    TCHAR path[MAX_PATH];

    if (SHGetPathFromIDList(pidlFolder, path)) {
        result += L"Path: "+ std::wstring(path) + L" \n ";
    }
    else {
        result += L"Failed to get path: ";
    }

    MessageBox(NULL, result.c_str(), L"", 0);

    return S_OK;
}
Share Improve this question asked Mar 21 at 8:58 Joe JJoe J 4839 bronze badges 3
  • 3 Just read the doc learn.microsoft/en-us/windows/win32/api/shobjidl_core/… For menu extensions, pdtobj identifies the selected file objects and pidlFolder is either NULL (for file objects) or specifies the folder for which the menu is being requested (for folder background menus). so instead use SHCreateShellItemArrayFromDataObject on pdtobj (there can be more than one item) and use IShellItem::GetDisplayName on each item – Simon Mourier Commented Mar 21 at 9:16
  • @SimonMourier Thank you. Your solution works fine: pastebin/iT36JBFs – Joe J Commented Mar 21 at 9:45
  • @SimonMourier that should be posted as a proper answer instead of a comment. – Remy Lebeau Commented Mar 21 at 15:58
Add a comment  | 

1 Answer 1

Reset to default 3

I quote the official IShellExtInit::Initialize method documentation:

For shortcut menu extensions, pdtobj identifies the selected file objects, hkeyProgID identifies the file type of the object with focus, and pidlFolder is either NULL (for file objects) or specifies the folder for which the shortcut menu is being requested (for folder background shortcut menus).

So in your case, pidlFolder is probably NULL, and anyway you're mostly interested by the selected Shell Item(s); there can be more than one item selected when the context menu was invoked.

So, instead, use the SHCreateShellItemArrayFromDataObject method on pdtobj, enumerate all Shell Items from there and use IShellItem::GetDisplayName on each item.

For the Shell Item's "name", note you can use SIGDN_FILESYSPATH if you're sure it's a file system file, but you can also use SIGDN_DESKTOPABSOLUTEPARSING for "virtual" Shell Items (items from other namespace extensions for example).

发布评论

评论列表(0)

  1. 暂无评论