Извлечь значок из файла Windows .lnk (ярлык)

Мне нужно извлечь значок из файла ярлыка Windows (.lnk) (или найти файл значка, если на него указывает ярлык).

Я не спрашиваю об извлечении значков из exe, dll и т. Д. Соответствующий ярлык создается при запуске программы установки. И значок, отображаемый ярлыком, не содержится в.exe, на который указывает ярлык. Предположительно значок встроен в файл.lnk, или файл.lnk содержит указатель на то, где находится этот значок. Но ни одна из утилит, которые я нашел, не работает с этим - все они просто идут в.exe.

Большое спасибо!

6 ответов

Решение

Этот поток предоставляет интересную информацию о данных, содержащихся в файле.lnk

Функция sSHGetFileInfoss должна иметь возможность извлекать файл значков.

Документировано здесь и используется для файла lnk:

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}

По первой ссылке вы можете создать такую ​​утилиту в C#, где вы объявите эту функцию следующим образом:

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

Вы также можете создать утилиту на языке сценариев autoit, где вы будете использовать эту функцию, объявленную так:

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

Используя метод Shell32 для обработки ссылок:

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();

В 2010 году Microsoft наконец-то выпустила официальную спецификацию формата файла LNK. Конечно, это гораздо точнее и детальнее, чем реверсивные спецификации, плавающие в сети.

Для полноты картины приведено описание ссылок и ярлыков оболочки в MSDN.

Вы также можете проанализировать файл.lnk самостоятельно, см. Этот PDF-файл или статью о деталях формата файла ярлыка.

Или вы можете использовать класс ShellLink, упомянутый в ответе на этот вопрос.

Я использую это, чтобы получить иконку без мини-иконки со стрелкой, добавленной над ней как изображение:

using IWshRuntimeLibrary;

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

Если вы хотите получить вместо него значок:

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

Чтобы добавить к этому еще несколько ресурсов, потому что, вероятно, вам не нужен значок приложения, а не значок с ярлыком в левом нижнем углу:

Другие вопросы по тегам