views:

235

answers:

3
+1  Q: 

find icon for .exe

I have the path name to a .exe file.

How do I find the path to the icon that windows would use if this file were dropped on the desktop? (I want to display this icon in my own program.)

I need to be able to find the icon via my C# program at runtime.

Using C# in Visual Studio 2008.

A: 

The default icon would be the one embedded in the exe at index 0.

Look at: Project properties > application tab > Icon.

Matt Lacey
Um... not really what I need. Guess I wasn't clear. I want to drop on ANY .exe using drag and drop (that is how I get the pathname) and then find the icon programatically.
Mark T
+5  A: 

If found this code online a while ago to do that:

class Win32
{
    public const uint SHGFI_ICON = 0x100;
    public const uint SHGFI_LARGEICON = 0x0; // 'Large icon
    public const uint SHGFI_SMALLICON = 0x1; // 'Small icon

    [DllImport("shell32.dll")]
    public static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);

    public static Bitmap GetFileIcon(string fName)
    {
        IntPtr hImgSmall; //the handle to the system image list
        SHFILEINFO shinfo = new SHFILEINFO();
        hImgSmall = Win32.SHGetFileInfo(fName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_SMALLICON);
        return Icon.FromHandle(shinfo.hIcon).ToBitmap();
    }
}


[StructLayout(LayoutKind.Sequential)]
public struct SHFILEINFO
{
    public IntPtr hIcon;
    public IntPtr iIcon;
    public uint dwAttributes;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
    public string szDisplayName;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
    public string szTypeName;
};

you also need

using System.Drawing;
using System.Runtime.InteropServices;

to reference all the appropriate classes

JDunkerley
The only thing I would add here is SHGFI_USEFILEATTRIBUTES = 0x010. From MSDN: If the uFlags parameter includes the SHGFI_USEFILEATTRIBUTES flag, this parameter does not have to be a valid file name. The function will proceed as if the file exists with the specified name and with the file attributes passed in the dwFileAttributes parameter. This allows you to obtain information about a file type by passing just the extension for pszPath and passing FILE_ATTRIBUTE_NORMAL in dwFileAttributes.
csharptest.net
This turned out to work more correctly for my need than the class recommended by Noldorin. Although the class could identify many icons, it sometimes did not find the one actually used. The code presented here seems to always find the same icon which is on the desktop. Many thanks.
Mark T
A: 

This CodeProject article seems to do the job pretty well. It provides an IconExtractor class that encapsulates all the Win32 API stuff for you into a nice managed interface.

You can use it as such:

using TKageyu.Utils;

...

using (IconExtractor ie = new IconExtractor(@"D:\sample.exe")) 
{
    Icon icon0 = ie.GetIcon(0);
    Icon icon1 = ie.GetIcon(1);

    ...

    Icon[] splitIcons = IconExtractor.SplitIcon(icon0);

    ...
}
Noldorin
Note that this returns a GDI+ (`System.Drawing`) icon, rather than a WPF one. I assume that's what you want though.
Noldorin
This was so easy to implement, and worked well. Thanks.
Mark T
No problen. And yeah, always handy to have a wrapper class for dealing with the Windows API.
Noldorin
So sorry... the negative vote was an accidental click... I tried to change it immediately and it said it was too old to change.
Mark T
@Mark T: I've edited my post, so you should be able to change it now.
Noldorin