How to Get the Icon from the Executable File Only Having an Instance of It's Process in C#

How can I get the icon from the executable file only having an instance of it's Process in C#

Icon ico = Icon.ExtractAssociatedIcon(theProcess.MainModule.FileName);

Get icon from Process List instead of File

You can find processes information using a WMI query on Win32_Process and use ExecutablePath to find executable path of the process. Then you can use Icon.ExtractAssociatedIcon to extract the associated icon of the process:

Example

Drop an ImageList on the form and set its ColorDepth to Depth32Bit and its ImageSize to 32,32. The drop a ListView on the form and set its LargImageList to imageList1 which you created in the first step.

Add reference to System.Management.dll and add using System.Management; and use below code to fill listView1 with icons:

var query = "SELECT ProcessId, Name, ExecutablePath FROM Win32_Process";
using (var searcher = new ManagementObjectSearcher(query))
using (var results = searcher.Get())
{
var processes = results.Cast<ManagementObject>().Select(x => new
{
ProcessId = (UInt32)x["ProcessId"],
Name = (string)x["Name"],
ExecutablePath = (string)x["ExecutablePath"]
});
foreach (var p in processes)
{
if (System.IO.File.Exists(p.ExecutablePath))
{
var icon = Icon.ExtractAssociatedIcon(p.ExecutablePath);
var key = p.ProcessId.ToString();
this.imageList1.Images.Add(key, icon.ToBitmap());
this.listView1.Items.Add(p.Name, key);
}
}
}

Then you will have such result:

enter image description here

Getting the icon associated with a running application

Icon ico = Icon.ExtractAssociatedIcon(theProcess.MainModule.FileName);

From TheSoftwareJedi

Initially this appears to be an exact duplicate of How can I get the icon from the executable file only having an instance of it's Process in C# but that one seems to focus largely on how to get it from within it's own self, whereas you may be asking how to get the icon using a program separate from the running process.

-Adam

Get icon 128*128 File type C#

There is no icon-size 128x128 available from the Shell API SHGetImageList. The sizes range from the Win95 era of 16x16 and 32x32 via XP's 48x48 and finally Vista that added the 256x256 size.

To get a png file from any of the available icon sizes I followed the blog How do I get a high resolution icon for a file from Raymond Chen. I ported his code to c# where I borrowed pieces from this answer.

To follow Raymond's article here are the main two functions you need:

    int GetIconIndex(string pszFile)
{
SHFILEINFO sfi = new SHFILEINFO();
Shell32.SHGetFileInfo(pszFile
, 0
, ref sfi
, (uint)System.Runtime.InteropServices.Marshal.SizeOf(sfi)
, (uint) (SHGFI.SysIconIndex | SHGFI.LargeIcon | SHGFI.UseFileAttributes));
return sfi.iIcon;
}

// 256*256
IntPtr GetJumboIcon(int iImage)
{
IImageList spiml = null;
Guid guil = new Guid(IID_IImageList2);//or IID_IImageList

Shell32.SHGetImageList(Shell32.SHIL_JUMBO, ref guil, ref spiml);
IntPtr hIcon = IntPtr.Zero;
spiml.GetIcon(iImage, Shell32.ILD_TRANSPARENT | Shell32.ILD_IMAGE, ref hIcon); //

return hIcon;
}

The method GetIconIndex calls into the native SHGetFileIfo to get the icon index for the file (or extension) you provided in the name parameter.

To get the actual icon the method GetJumboIcon calls the native SHGetImageList with a size attribute.

To let it all work you combine the calls like so:

IntPtr hIcon = GetJumboIcon(GetIconIndex("*.txt"));

// from native to managed
using (Icon ico = (Icon)System.Drawing.Icon.FromHandle(hIcon).Clone())
{
// save to file (or show in a picture box)
ico.ToBitmap().Save("txticon.png", ImageFormat.Png);
}
Shell32.DestroyIcon(hIcon); // don't forget to cleanup

To get an 48x48 icon you can extend the code with this method:

    // 48X48
IntPtr GetXLIcon(int iImage)
{
IImageList spiml = null;
Guid guil = new Guid(IID_IImageList);//or IID_IImageList

Shell32.SHGetImageList(Shell32.SHIL_EXTRALARGE, ref guil, ref spiml);
IntPtr hIcon = IntPtr.Zero;
spiml.GetIcon(iImage, Shell32.ILD_TRANSPARENT | Shell32.ILD_IMAGE, ref hIcon); //

return hIcon;
}

Due to interaction with unmanaged code you need to compile the project with the /unsafe option enabled. You can set that from visual studio by changing the project properties, goto to the Build tab and put a checkmark for the Allow unsafe code option. See this question why that is needed and here is the official MSDN documentation

Native wrapper

To call the native win32 api the functions and structures are wrapped in a static class that you need to include as well in your project. Most of those wrappers and the structures can be found at Pinvoke.net

const string IID_IImageList = "46EB5926-582E-4017-9FDF-E8998DAA0950";
const string IID_IImageList2 = "192B9D83-50FC-457B-90A0-2B82A8B5DAE1";

public static class Shell32
{

public const int SHIL_LARGE =0x0;
public const int SHIL_SMALL =0x1;
public const int SHIL_EXTRALARGE =0x2;
public const int SHIL_SYSSMALL =0x3;
public const int SHIL_JUMBO = 0x4;
public const int SHIL_LAST = 0x4;

public const int ILD_TRANSPARENT = 0x00000001;
public const int ILD_IMAGE = 0x00000020;

[DllImport("shell32.dll", EntryPoint = "#727")]
public extern static int SHGetImageList(int iImageList, ref Guid riid, ref IImageList ppv);

[DllImport("user32.dll", EntryPoint = "DestroyIcon", SetLastError = true)]
public static unsafe extern int DestroyIcon(IntPtr hIcon);

[DllImport("shell32.dll")]
public static extern uint SHGetIDListFromObject([MarshalAs(UnmanagedType.IUnknown)] object iUnknown, out IntPtr ppidl);

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

Native structures

[Flags]
enum SHGFI : uint
{
/// <summary>get icon</summary>
Icon = 0x000000100,
/// <summary>get display name</summary>
DisplayName = 0x000000200,
/// <summary>get type name</summary>
TypeName = 0x000000400,
/// <summary>get attributes</summary>
Attributes = 0x000000800,
/// <summary>get icon location</summary>
IconLocation = 0x000001000,
/// <summary>return exe type</summary>
ExeType = 0x000002000,
/// <summary>get system icon index</summary>
SysIconIndex = 0x000004000,
/// <summary>put a link overlay on icon</summary>
LinkOverlay = 0x000008000,
/// <summary>show icon in selected state</summary>
Selected = 0x000010000,
/// <summary>get only specified attributes</summary>
Attr_Specified = 0x000020000,
/// <summary>get large icon</summary>
LargeIcon = 0x000000000,
/// <summary>get small icon</summary>
SmallIcon = 0x000000001,
/// <summary>get open icon</summary>
OpenIcon = 0x000000002,
/// <summary>get shell size icon</summary>
ShellIconSize = 0x000000004,
/// <summary>pszPath is a pidl</summary>
PIDL = 0x000000008,
/// <summary>use passed dwFileAttribute</summary>
UseFileAttributes = 0x000000010,
/// <summary>apply the appropriate overlays</summary>
AddOverlays = 0x000000020,
/// <summary>Get the index of the overlay in the upper 8 bits of the iIcon</summary>
OverlayIndex = 0x000000040,
}

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

[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left, top, right, bottom;
}

[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
int x;
int y;
}

[StructLayout(LayoutKind.Sequential)]
public struct IMAGELISTDRAWPARAMS
{
public int cbSize;
public IntPtr himl;
public int i;
public IntPtr hdcDst;
public int x;
public int y;
public int cx;
public int cy;
public int xBitmap; // x offest from the upperleft of bitmap
public int yBitmap; // y offset from the upperleft of bitmap
public int rgbBk;
public int rgbFg;
public int fStyle;
public int dwRop;
public int fState;
public int Frame;
public int crEffect;
}

[StructLayout(LayoutKind.Sequential)]
public struct IMAGEINFO
{
public IntPtr hbmImage;
public IntPtr hbmMask;
public int Unused1;
public int Unused2;
public RECT rcImage;
}
[ComImportAttribute()]
[GuidAttribute("46EB5926-582E-4017-9FDF-E8998DAA0950")]
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
public interface IImageList
{
[PreserveSig]
int Add(
IntPtr hbmImage,
IntPtr hbmMask,
ref int pi);

[PreserveSig]
int ReplaceIcon(
int i,
IntPtr hicon,
ref int pi);

[PreserveSig]
int SetOverlayImage(
int iImage,
int iOverlay);

[PreserveSig]
int Replace(
int i,
IntPtr hbmImage,
IntPtr hbmMask);

[PreserveSig]
int AddMasked(
IntPtr hbmImage,
int crMask,
ref int pi);

[PreserveSig]
int Draw(
ref IMAGELISTDRAWPARAMS pimldp);

[PreserveSig]
int Remove(
int i);

[PreserveSig]
int GetIcon(
int i,
int flags,
ref IntPtr picon);

[PreserveSig]
int GetImageInfo(
int i,
ref IMAGEINFO pImageInfo);

[PreserveSig]
int Copy(
int iDst,
IImageList punkSrc,
int iSrc,
int uFlags);

[PreserveSig]
int Merge(
int i1,
IImageList punk2,
int i2,
int dx,
int dy,
ref Guid riid,
ref IntPtr ppv);

[PreserveSig]
int Clone(
ref Guid riid,
ref IntPtr ppv);

[PreserveSig]
int GetImageRect(
int i,
ref RECT prc);

[PreserveSig]
int GetIconSize(
ref int cx,
ref int cy);

[PreserveSig]
int SetIconSize(
int cx,
int cy);

[PreserveSig]
int GetImageCount(
ref int pi);

[PreserveSig]
int SetImageCount(
int uNewCount);

[PreserveSig]
int SetBkColor(
int clrBk,
ref int pclr);

[PreserveSig]
int GetBkColor(
ref int pclr);

[PreserveSig]
int BeginDrag(
int iTrack,
int dxHotspot,
int dyHotspot);

[PreserveSig]
int EndDrag();

[PreserveSig]
int DragEnter(
IntPtr hwndLock,
int x,
int y);

[PreserveSig]
int DragLeave(
IntPtr hwndLock);

[PreserveSig]
int DragMove(
int x,
int y);

[PreserveSig]
int SetDragCursorImage(
ref IImageList punk,
int iDrag,
int dxHotspot,
int dyHotspot);

[PreserveSig]
int DragShowNolock(
int fShow);

[PreserveSig]
int GetDragImage(
ref POINT ppt,
ref POINT pptHotspot,
ref Guid riid,
ref IntPtr ppv);

[PreserveSig]
int GetItemFlags(
int i,
ref int dwFlags);

[PreserveSig]
int GetOverlayImage(
int iOverlay,
ref int piIndex);
};

Process/ProcessStartInfo Icon

The icon is associated with the executable file of that process so you can't change it. As the only workaround you may create a shortcut to the executable and set a custom icon for the shortcut. Then you can pass the path to the shortcut file into Process.Start (you need to add a COM reference to Windows Script Host Object Model via Project > Add Reference > COM > Windows Script Host Object Model for this to work):

using System;
using System.Diagnostics;
using IWshRuntimeLibrary;

class Program
{
private static void Main(string[] args)
{
string shortcutAddress = Environment.GetFolderPath(
Environment.SpecialFolder.Desktop) + @"\MyProcess.lnk";

var shell = new WshShell();
var shortcut = (IWshShortcut)shell.CreateShortcut(shortcutAddress);
shortcut.Description = "New shortcut for a Notepad";
shortcut.Hotkey = "Ctrl+Shift+N";
shortcut.TargetPath = Environment.GetFolderPath(
Environment.SpecialFolder.System) + @"\notepad.exe";
shortcut.IconLocation = Environment.GetFolderPath(
Environment.SpecialFolder.System) + @"\calc.exe";
shortcut.Save();

Process.Start(shortcutAddress);
}
}

Getting the icon representing a process with VB.net

Does the technique in this answer help?

The VB equivalent would be:

Dim ico As Icon = Icon.ExtractAssociatedIcon(theProcess.MainModule.FileName)

How to get the full path of running process?

 using System.Diagnostics;
var process = Process.GetCurrentProcess(); // Or whatever method you are using
string fullPath = process.MainModule.FileName;
//fullPath has the path to exe.

There is one catch with this API, if you are running this code in 32 bit application, you'll not be able to access 64-bit application paths, so you'd have to compile and run you app as 64-bit application (Project Properties → Build → Platform Target → x64).



Related Topics



Leave a reply



Submit