Question

I need to extract the icon from a windows shortcut (.lnk) file (or find the icon file, if it's just pointed to by the shortcut).

I'm not asking about extracting icons from exe's, dll's, etc. The shortcut in question is created when I run a installation program. And the icon displayed by the shortcut is not contained in the .exe that the shortcut points to. Presumably the icon is embedded in the .lnk file, or the .lnk file contains a pointer to where this icon lives. But none of the utilities I've found work address this -- they all just go to the .exe.

Many thanks!

Was it helpful?

Solution

This thread provides interesting informations about the data contained in a .lnk file

The sSHGetFileInfoss function should be able to extract the icon file.

Documented here, and used for a lnk file:

Path2Link := 'C:\Stuff\TBear S Saver.lnk';
SHGetFileInfo(PChar(Path2Link), 0, ShInfo1, SizeOf(TSHFILEINFO),
          SHGFI_ICON);
// this ShInfo1.hIcon will have the Icon Handle for the Link Icon with
// the small ShortCut arrow added}

From the first link, you could build such an utility in c#, where you would declare this function like:

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

You could also built an utility in autoit script language, where you would use that function declared like this:

Func _ShellGetAssocIcon(Const $szFile,Const $IconFlags = 0)
    Local $tFileInfo = DllStructCreate($tagSHFILEINFO)
    If @error Then
        Return SetError(1,@extended,0)
    EndIf

    Local $Ret = DllCall("shell32.dll","int","SHGetFileInfo","str",$szFile,"dword",0, _
        "ptr",DllStructGetPtr($tFileInfo),"uint",DllStructGetSize($tFileInfo),"uint",BitOr($SHGFI_ICON,$IconFlags))
    MsgBox(0,0,@error)
    Return DllStructGetData($tFileInfo,"hIcon")
EndFunc

OTHER TIPS

Using the Shell32 method of acessing links:

String lnkPath = @"C:\Users\PriceR\Desktop\Microsoft Word 2010.lnk";
//--- run microsoft word
var shl = new Shell32.Shell();         // Move this to class scope
lnkPath = System.IO.Path.GetFullPath(lnkPath);
var dir = shl.NameSpace(System.IO.Path.GetDirectoryName(lnkPath));
var itm = dir.Items().Item(System.IO.Path.GetFileName(lnkPath));
var lnk = (Shell32.ShellLinkObject)itm.GetLink;
//lnk.GetIconLocation(out strIcon);
String strIcon;
lnk.GetIconLocation(out strIcon);
Icon awIcon = Icon.ExtractAssociatedIcon(strIcon);
this.button1.Text = "";
this.button1.Image = awIcon.ToBitmap();

In 2010 Microsoft finally released an official specification of the LNK file format. It much more accurate and detailed than the reverse-engineered specs floating around the net, of course.

For completeness sake, here is the MSDN description of shell links and shortcuts.

You can also parse the .lnk file yourself, see this pdf or this article on the details of the shortcut file format.

Or you can use the ShellLink class mentioned in the answer to this question.

To add a few more resources to this, because presumeably you wan't the Application's icon and not icon that has the shortcut in the bottom left corner:

I use this to get the icon without the shortcut arrow mini icon added over it as an image:

using IWshRuntimeLibrary;

Image ShortcutIcon = System.Drawing.Icon.ExtractAssociatedIcon(((IWshShortcut)new WshShell().CreateShortcut(File)).TargetPath).ToBitmap();

If you wish to get it as an icon instead:

Icon ShortcutIcon = System.Drawing.Icon.ExtractAssociatedIcon(((IWshShortcut)new WshShell().CreateShortcut(File)).TargetPath);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top