Извлечь значок из файла 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);
Чтобы добавить к этому еще несколько ресурсов, потому что, вероятно, вам не нужен значок приложения, а не значок с ярлыком в левом нижнем углу: