In .Net (C# or VB: don't care), given a file path string, FileInfo struct, or FileSystemInfo struct for a real existing file, how can I determine the icon(s) used by the shell (explorer) for that file?
I'm not currently planning to use this for anything, but I became curious about how to do it when looking at this question and I thought it would be useful to have archived here on SO.
The problem with the registry approach is that you are not explicitly getting the icon index id. Sometimes (if not all times), you get an icon ResourceID which is an alias the application developer used to name the icon's slot.
The registry method therefore implies that all developers use ResourceIDs which are the same as the implicit icon index id (which is zero based, absolute, deterministic).
Scan the registry location and you will see lots of negative numbers, sometimes even text references - i.e. not the icon index id. An implicit method seems better as it lets the OS do the work.
Only testing this new method now but it makes sense and hopefully solves this problem.
If you're only interested in an icon for a specific extension and if you don't mind creating a temporary file you can follow the example displayed here
C# code:
Nothing more than a C# version of Stefan's answer.
Please ignore everyone telling you to use the registry! The registry is NOT AN API. The API you want is SHGetFileInfo with SHGFI_ICON. You can get a P/Invoke signature here:
http://www.pinvoke.net/default.aspx/shell32.SHGetFileInfo
You should use SHGetFileInfo.
Icon.ExtractAssociatedIcon works just as well as SHGetFileInfo in most cases, but SHGetFileInfo can work with UNC paths (e.g. a network path like "\\ComputerName\SharedFolder\") while Icon.ExtractAssociatedIcon cannot. If you need or might need to use UNC paths, it would be best to use SHGetFileInfo instead of Icon.ExtractAssociatedIcon.
This is good CodeProject article on how to use SHGetFileInfo.