I found several examples yesterday, including in C++ and tried to make it work on my own, but it didn't work out and I had to search more carefully in the code archives using function names and I found a ready-made example. But since you only asked for the icon, I did it only for the icon, but in my example from the Internet there were functions for other fields of the structure, if you need them:
Code: Select all
;Autor: bembulak
EnableExplicit
#STGM_READ = 0
#SLGP_SHORTPATH = 1
#SLGP_UNCPRIORITY = 2
#SLGP_RAWPATH = 4
#SLGP_RELATIVEPRIORITY = 8
Define File$ = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\7-Zip\7-Zip File Manager.lnk"
Define psl.IShellLinkA
Define ppf.IPersistFile
Define OutSpace$
Define hres
Define Path$
Define udata.WIN32_FIND_DATA
Define Argument$
Define WorkingDirectory$
Define DESCRIPTION$
Define ShowCommand.l
Define HotKey
Define IconFile$
Define IconIndexInFile
Define rclsid.CLSID, riid.CLSID, riid2.CLSID
CLSIDFromString_("{00021401-0000-0000-C000-000000000046}", @rclsid)
IIDFromString_("{000214EE-0000-0000-C000-000000000046}", @riid)
IIDFromString_("{0000010b-0000-0000-C000-000000000046}", @riid2)
CoInitialize_(0)
; If CoCreateInstance_(?CLSID_ShellLink, 0, #CLSCTX_INPROC_SERVER, ?IID_IShellLink, @psl.IShellLinkA) = 0
If CoCreateInstance_(@rclsid, #Null, #CLSCTX_INPROC_SERVER, @riid, @psl) = #S_OK
Debug psl ; указатель не должен быть равен 0
; If psl\QueryInterface(?IID_IPersistFile, @ppf.IPersistFile) >= 0
If psl\QueryInterface(@riid2, @ppf) = #S_OK
OutSpace$ = Space(#MAX_PATH)
MultiByteToWideChar_(#CP_ACP, 0, @File$, -1, @OutSpace$, #MAX_PATH) ; в UTF-8
hres = ppf\Load(OutSpace$, #STGM_READ)
; hres = psl\Resolve(0, 0);
Debug hres
Debug OutSpace$
EndIf
Path$=Space(#MAX_PATH)
If psl\GetPath(Path$, #MAX_PATH, udata.WIN32_FIND_DATA, #SLGP_SHORTPATH)
Debug "1=" + Path$
EndIf
; Arguments for the Target
Argument$ = Space(256)
psl\GetArguments(@Argument$,Len(Argument$))
Debug "2=" + Argument$
; Working Directory
WorkingDirectory$ = Space(#MAX_PATH)
psl\GetWorkingDirectory(@WorkingDirectory$,Len(WorkingDirectory$))
Debug "3=" + WorkingDirectory$
; Description ( also used as Tooltip for the Link )
;
DESCRIPTION$ = Space(4096)
psl\GetDescription(@DESCRIPTION$,Len(DESCRIPTION$))
Debug "4=" + DESCRIPTION$
; Show command:
; SW_SHOWNORMAL = Default
; SW_SHOWMAXIMIZED = aehmm... Maximized
; SW_SHOWMINIMIZED = play Unreal Tournament
ShowCommand.l = 0
psl\GetShowCmd(@ShowCommand)
psl\GetHotkey(@HotKey)
; Set Icon for the Link:
; There can be more than 1 icons in an icon resource file,
; so you have to specify the index.
;
IconFile$ = Space(#MAX_PATH)
psl\getIconLocation(@IconFile$, Len(IconFile$),@IconIndexInFile)
Debug IconFile$
psl\Release()
ppf\Release()
EndIf
CoUninitialize_()
DataSection
CLSID_ShellLink:
; 00021401-0000-0000-C000-000000000046
Data.l $00021401
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46
IID_IShellLink:
; DEFINE_SHLGUID(IID_IShellLinkA, 0x000214EEL, 0, 0);
; C000-000000000046
; 000214EE-0000-0000-C000-000000000046
Data.l $000214EE
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46
IID_IPersistFile:
; 0000010b-0000-0000-C000-000000000046
Data.l $0000010b
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46
EndDataSection
As you can see, there are functions here:
Code: Select all
psl\GetPath
psl\GetArguments
psl\GetWorkingDirectory
psl\GetDescription
psl\GetShowCmd
psl\GetHotkey
psl\getIconLocation
Therefore, you do not have to explore the binary file
Here is a ready example
Code: Select all
EnableExplicit
Procedure$ GetShellLinkTargetPath(shellLinkFilePath$)
Protected Path$ = Space(#MAX_PATH + 1)
Protected Argument$ = Space(#MAX_PATH + 1)
Protected WorkingDirectory$ = Space(#MAX_PATH + 1)
Protected Description$ = Space(#MAX_PATH + 1)
Protected IconFile$ = Space(#MAX_PATH + 1)
Protected IconIndexInFile.l
Protected ShowCommand.l
Protected Hotkey
Protected linkFile.IPersistFile
Protected shellLink.IShellLinkW
CoInitialize_(0)
If CoCreateInstance_(?CLSID_ShellLink, 0, 1, ?IID_IShellLink, @shellLink) = #S_OK
If shellLink\QueryInterface(?IID_IPersistFile, @linkFile) = #S_OK
If linkFile\Load(shellLinkFilePath$, 0) = #S_OK
If shellLink\Resolve(0, 1) = #S_OK
shellLink\GetPath(@Path$, #MAX_PATH, 0, 0)
shellLink\GetArguments(@Argument$, #MAX_PATH)
shellLink\GetWorkingDirectory(@WorkingDirectory$, #MAX_PATH)
shellLink\GetDescription(@Description$, #MAX_PATH)
shellLink\GetShowCmd(@ShowCommand)
shellLink\GetHotkey(@Hotkey)
shellLink\getIconLocation(@IconFile$, #MAX_PATH, @IconIndexInFile)
Debug Path$
Debug Argument$
Debug WorkingDirectory$
Debug Description$
Debug ShowCommand
Debug Hotkey
Debug IconFile$
Debug IconIndexInFile
EndIf
EndIf
LinkFile\Release()
EndIf
shellLink\Release()
EndIf
CoUninitialize_()
DataSection
CLSID_ShellLink:
; 00021401-0000-0000-C000-000000000046
Data.l $00021401
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46
IID_IShellLink:
CompilerIf #PB_Compiler_Unicode
; IID_IShellLinkW
; {000214F9-0000-0000-C000-000000000046}
Data.l $000214F9
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46
CompilerElse
; 000214EE-0000-0000-C000-000000000046
Data.l $000214EE
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46
CompilerEndIf
IID_IPersistFile:
; 0000010b-0000-0000-C000-000000000046
Data.l $0000010b
Data.w $0000,$0000
Data.b $C0,$00,$00,$00,$00,$00,$00,$46
EndDataSection
EndProcedure
GetShellLinkTargetPath("C:\ProgramData\Microsoft\Windows\Start Menu\Programs\7-Zip\7-Zip File Manager.lnk")
I think there shouldn't be a #MAX_PATH for getDescription, maybe 4096. Checked, 259 (+Null), and #MAX_PATH=260