Windows 7 - Getting Icon Path and Index

Asked By Mar on 18-Jun-07 01:28 PM
I am trying to get the Icon path and Index (If available) so that I can use
it as a unique identifier for the icon. Currently im using the
SHGetFileInfo() funciton to get the index and pixel data but it does not give
me any information about where this icon resides (ie. path, or path to a DLL
and index). I tried to piece some code form the MSN pages but it does not
retrieve the right path. Any help is appreciated! Thanks


Code:

void GetIconInfo(char *FileName)
{
LPITEMIDLIST  Pidl;
LPSHELLFOLDER DesktopFolder;
OLECHAR       OlePath[MAX_PATH];
ULONG         Attributes;
HRESULT       hr;
IExtractIcon* Extract;
TCHAR		  Path[MAX_PATH];
unsigned Flags;
int Index;

if (SUCCEEDED(SHGetDesktopFolder(&DesktopFolder)))
{
// Convert to Unicode
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, FileName, -1, OlePath, MAX_PATH);

// Convert the path to an ITEMIDLIST.
hr = DesktopFolder->ParseDisplayName(NULL, NULL, OlePath, NULL,
(LPITEMIDLIST *) &Pidl, &Attributes);

if (SUCCEEDED(hr))
{
// Populate the Icon Extract Interface
hr = DesktopFolder->GetUIObjectOf(NULL, 1, (LPCITEMIDLIST *) &Pidl,
IID_IExtractIcon, 0, (void **) &Extract);

if (SUCCEEDED(hr))
{
// retrieve the Icon Path and Index
if (SUCCEEDED(Extract->GetIconLocation(GIL_FORSHELL, Path, _MAX_PATH,
&Index, &Flags)))
{
if (!(Flags & GIL_NOTFILENAME))
{
if (Index == -1)
{
// Special case for Control Panel Apps
Index = 0;
}
}
// **** Path and Index are not correct values ****
}

Extract->Release();
}
}


//release the desktop folder object
DesktopFolder->Release();
}
}




Igor Tandetnik replied on 18-Jun-07 01:45 PM
Does too. Call it with SHGFI_ICONLOCATION flag. The icon location is
returned in szDisplayName and iIcon members of SHFILEINFO structure.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Mar replied on 18-Jun-07 03:21 PM
I have tried using this method but it only returns the index and not the file
that holds the Icon (.ICO, .DLL, .EXE). Her eis my previous implementation:

SHFILEINFO FileInfo;
SHGetFileInfo(FileName,
0,
&FileInfo,
sizeof(SHFILEINFO),
SHGFI_ICONLOCATION);

szDisplayName ends up being a NULL string.
Am I missing some critical flag???

-Mark
Igor Tandetnik replied on 18-Jun-07 04:32 PM
You are right, SHGetFileInfo doesn't appear to work. See my other
response.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Igor Tandetnik replied on 18-Jun-07 04:38 PM
You cannot get IExtractIcon directly from desktop folder. You have to do
it on the parent folder of the file you are trying to get the icon from.
After ParseDisplayName call, do this:

IShellFolder* parent;
LPCITEMIDLIST pidlRelative;
SHBindToParent(Pidl, IID_IShellFolder, (void**)&parent, &pidlRelative);

Then call parent->GetUIObjectOf(), passing pidlRelative as a parameter.
Be aware that, in a lot of cases, you'll get GIL_NOTFILENAME flag back,
which means the icon is dynamically generated by the icon handler and
does not come from any particular file.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Igor Tandetnik replied on 18-Jun-07 04:43 PM
Ah, now I understand why SHGetFileInfo(SHGFI_ICONLOCATION) doesn't work
for me. I have TortoiseSVN installed, which registers a shell icon
handler for all files on the file system. So now, when going through
IExtractIcon::GetIconLocation, I get GIL_NOTFILENAME for any file.
SHGetFileInfo goes through the same motions and simply reports an empty
file name in this case (I get the same icon index both from
GetIconLocation and from SHGetFileInfo, which suggests the two
approaches are doing the same thing after all).

So SHGetFileInfo(SHGFI_ICONLOCATION) does work, it's just that many
shell icons simply cannot be represented by path/index pair.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925
Mar replied on 18-Jun-07 05:49 PM
Thanks so much, I am getting the correct path name now and the expected
astrix (*) back from when the icon is in memory. One question remains though,
will this be vista compatible?

-mark