May 1st, 2017

Why doesn’t SHGetFileInfo give me customized folder icons?

A customer reported that they were unable to obtain cutomized folder icons. Whenever they asked for the icon for a folder, they always got a plain folder icon, Even if they asked for folders like My Documents, which come with their own custom icons. The customer says that they are using the code from this Web site:

public static System.Drawing.Icon GetFileIcon(string name, IconSize size, 
                                              bool linkOverlay)
{
    Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
    uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_USEFILEATTRIBUTES;
    
    if (true == linkOverlay) flags += Shell32.SHGFI_LINKOVERLAY;


    /* Check the size specified for return. */
    if (IconSize.Small == size)
    {
        flags += Shell32.SHGFI_SMALLICON ; // include the small icon flag
    } 
    else 
    {
        flags += Shell32.SHGFI_LARGEICON ;  // include the large icon flag
    }
    
    Shell32.SHGetFileInfo( name, 
        Shell32.FILE_ATTRIBUTE_NORMAL, 
        ref shfi, 
        (uint) System.Runtime.InteropServices.Marshal.SizeOf(shfi), 
        flags );


    // Copy (clone) the returned icon to a new object, thus allowing us 
    // to call DestroyIcon immediately
    System.Drawing.Icon icon = (System.Drawing.Icon)
                         System.Drawing.Icon.FromHandle(shfi.hIcon).Clone();
    User32.DestroyIcon( shfi.hIcon ); // Cleanup
    return icon;
}

As I noted some time ago, the SHGFI_USE­FILE­ATTRIBUTES flag means “Pretend that the file/directory exists, and that its file attributes are what I passed as the dwFileAttributes parameter. Do this regardless of whether it actually exists or not.”

Since you’re passing the flag, and you say “Trust me, it’s a directory,” the shell says, “Okay, then here’s the icon for a standard directory. I can’t give you anything better than that because you told me not to access the disk.”

If you want to get the icon for a live file or directory, then remove the SHGFI_USE­FILE­ATTRIBUTES flag.

Bonus chatter: Yes, somebody posted a comment on that Web site asking how to get the function to work for special folders, and somebody else posted the same answer (namely, remove the SHGFI_USE­FILE­ATTRIBUTES flag). But that question/answer was posted long after our customer asked the question.

Topics
Code

Author

Raymond has been involved in the evolution of Windows for more than 30 years. In 2003, he began a Web site known as The Old New Thing which has grown in popularity far beyond his wildest imagination, a development which still gives him the heebie-jeebies. The Web site spawned a book, coincidentally also titled The Old New Thing (Addison Wesley 2007). He occasionally appears on the Windows Dev Docs Twitter account to tell stories which convey no useful information.

0 comments

Discussion are closed.