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 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).