Get File Icon used by Shell

2019-01-03 09:15发布

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.

9条回答
【Aperson】
2楼-- · 2019-01-03 09:53
Imports System.Drawing
Module Module1

    Sub Main()    
        Dim filePath As String =  "C:\myfile.exe"  
        Dim TheIcon As Icon = IconFromFilePath(filePath)  

        If TheIcon IsNot Nothing Then    
            ''#Save it to disk, or do whatever you want with it.
            Using stream As New System.IO.FileStream("c:\myfile.ico", IO.FileMode.CreateNew)
                TheIcon.Save(stream)          
            End Using
        End If
    End Sub

    Public Function IconFromFilePath(filePath As String) As Icon
        Dim result As Icon = Nothing
        Try
            result = Icon.ExtractAssociatedIcon(filePath)
        Catch ''# swallow and return nothing. You could supply a default Icon here as well
        End Try
        Return result
    End Function
End Module
查看更多
Animai°情兽
3楼-- · 2019-01-03 09:53

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.

查看更多
三岁会撩人
4楼-- · 2019-01-03 09:55

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:

    public Icon LoadIconFromExtension(string extension)
    {
        string path = string.Format("dummy{0}", extension);
        using (File.Create(path)) { }
        Icon icon = Icon.ExtractAssociatedIcon(path);
        File.Delete(path);
        return icon;
    }
查看更多
叛逆
5楼-- · 2019-01-03 09:58

Nothing more than a C# version of Stefan's answer.

using System.Drawing;

class Class1
{
    public static void Main()
    {
        var filePath =  @"C:\myfile.exe";
        var theIcon = IconFromFilePath(filePath);

        if (theIcon != null)
        {
            // Save it to disk, or do whatever you want with it.
            using (var stream = new System.IO.FileStream(@"c:\myfile.ico", System.IO.FileMode.CreateNew))
            {
                theIcon.Save(stream);
            }
        }
    }

    public static Icon IconFromFilePath(string filePath)
    {
        var result = (Icon)null;

        try
        {
            result = Icon.ExtractAssociatedIcon(filePath);
        }
        catch (System.Exception)
        {
            // swallow and return nothing. You could supply a default Icon here as well
        }

        return result;
    }
}
查看更多
何必那么认真
6楼-- · 2019-01-03 10:00

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

查看更多
我只想做你的唯一
7楼-- · 2019-01-03 10:11

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.

查看更多
登录 后发表回答