-1

I'm on Windows 10 Pro and Visual Studio 2013, and I'm using SHGetFileInfoW to get an icon location (path + index) for a file type:

std::wstring wFile { L"a.bas" };
SHFILEINFOW fi {};    
DWORD success = ::SHGetFileInfoW(wFile.c_str(), 
                                 FILE_ATTRIBUTE_NORMAL, 
                                 &fi, 
                                 sizeof(fi),
                                 SHGFI_USEFILEATTRIBUTES | SHGFI_ICONLOCATION);

No matter whether wFile refers to an existing file or is just any filename, the call returns 1 indicating success. The iIcon member of fi is set to a number, but szDisplayString is empty. Not just the drive letter is overwritten with \0 (as seemed to happen here) but it is completely filled with \0.

Microsoft recommends using IExtractIcon::GetIconLocation as an alternative, but I need to get the icon for files which are not on a local filesystem, so I can't get an IShellInfo object which would get me this interface pointer.

Getting an icon handle works, on the other hand. Is this function just buggy or am I doing something wrong? Is there a workaround?

Community
  • 1
  • 1
Felix Dombek
  • 13,664
  • 17
  • 79
  • 131
  • @Ðаn `bas` doesn't even return an index, `.bas` works just like `a.bas` and returns index, but not path. The documentation seems to be sloppy there. – Felix Dombek Mar 08 '17 at 16:21
  • @Ðаn Aren't icons usually stored in their associated executable (.pdf = Acrobat Reader, .7z = 7zip etc.)? I think this method should work at least for some extensions (I've tried many). I thought something might have changed in Windows 10, but then I found [this question](http://stackoverflow.com/questions/18308866/shgetfileinfo-not-return-the-icon-location) from 2013 ... without any answers. – Felix Dombek Mar 08 '17 at 16:46
  • 1
    Why do you need the icon location? Simply use SHGFI_ICON flag and let the system give you an icon handle and an index into the system icon list to you. If you want to look up the icon in the system image list yourself, use SHGFI_SYSICONINDEX. – zett42 Mar 08 '17 at 16:58
  • "*Aren't icons usually stored in their associated executable*" - sometimes, but not always. – Remy Lebeau Mar 08 '17 at 21:34

1 Answers1

3

Icons can be dynamically generated and might not expose the path to its images. Icon handlers communicate this to the shell by setting the GIL_NOTFILENAME flag in their IExtractIcon::GetIconLocation implementation. If GIL_SIMULATEDOC is set the shell must also typically generate a icon on the fly.

If you call SHGetFileInfo with the SHGFI_SELECTED flag set then then function probably has to generate a new icon no matter which file type you are asking for.

If you are displaying a file list in a ListView/TreeView then you typically use SHGFI_SYSICONINDEX|SHGFI_SHELLICONSIZE|SHGFI_SMALLICON and use the system image list.

Use SHGFI_ICON if you need a HICON.

If SHGFI_ICONLOCATION is specified then SHGetFileInfo uses IExtractIcon:

Retrieve the name of the file that contains the icon representing the file specified by pszPath, as returned by the IExtractIcon::GetIconLocation method of the file's icon handler.

Anders
  • 97,548
  • 12
  • 110
  • 164