Retrieve icon (link / filename) from a .LNK file

Windows specific forum
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6161
Joined: Sat May 17, 2003 11:31 am
Contact:

Retrieve icon (link / filename) from a .LNK file

Post by blueznl »

I'm looking for a way to retrieve the icon (I think it's only a path to the icon file) from a .lnk (shortcut) file.

I've found some examples on the Internet, but it seems they're all object based (the only object oriented coding I understand is throwing heavy objects at my screen when something doesn't work).

Another way might be to deduce the structure of the .LNK file, and I found some descriptions, but couldn't get those to work yet.

Anyone that tried to retrieve such information from a .LNK file? (And was succesful :) )
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
AZJIO
Addict
Addict
Posts: 1318
Joined: Sun May 14, 2017 1:48 am

Re: Retrieve icon (link / filename) from a .LNK file

Post by AZJIO »

link
example

Code: Select all

Procedure$ GetShellLinkTargetPath(shellLinkFilePath$)
	
	Protected result$ = Space(#MAX_PATH + 1)
	Protected linkFile.IPersistFile
	Protected shellLink.IShellLinkW
	Protected IconIndexInFile.l
	
	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(@result$, #MAX_PATH, 0, 0)
					shellLink\getIconLocation(@result$, #MAX_PATH, @IconIndexInFile)
					Debug IconIndexInFile
					Debug result$
				EndIf
			EndIf
			LinkFile\Release()
		EndIf
		shellLink\Release()
	EndIf
	
	CoUninitialize_()
	
	ProcedureReturn result$
	
	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:\Users\user\Desktop\reboot.lnk")
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6161
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Retrieve icon (link / filename) from a .LNK file

Post by blueznl »

Hmmmm.

Interesting.

I dove a bit into the .LNK file, trying to figure out the contents / structure. Looks like MS's documentation is a little confusing :-)

I found some of the information I was looking for, and it turns out there are many different ways of using .LNK files. Code below may be of interest to those trying to puzzle it out (I found what I was looking for, but there are some cases where .LNK files contain very weird field combos).

Try the code below on different .LNK files, sometimes it manages to find the proper destination, but I found a few cases it would not, where Windows would still manage to launch the program. I suspect it's a fallback to what's contained inside the LinkInfo section.

Code: Select all

EnableExplicit
Declare init()
Declare main()
init()
main()

Procedure init()
  ;
  Structure shelllinkheader
    headersize.l              ; 4 bytes, always contains $0000004C (dec 76) in reverse byte order (?)
    linkclsid.b[16]           ; 16 bytes, SHOULD contain $00021401-0000-0000-C000-000000000046 but I've found other values
    linkflags.l               ; 4 bytes, defining all optional fields in the .lnk file
    fileattributes.b[4]
    creationtime.FILETIME     ; 8 bytes, creation time of link target in UTC
    accesstime.FILETIME       ; 8 bytes, last access time to link target
    writetime.FILETIME        ; 8 bytes,  last write to link target in UTC
    filesize.b[4]
    iconindex.b[4]
    showcommand.b[4]
    hotkey.b[2]
    reserved1.b[2]
    reserved2.b[4]
    reserved3.b[4]
  EndStructure
  ;
  ; Debug SizeOf(shelllinkheader)
  ;
EndProcedure

Procedure.s peekhex(p,n)
  Protected x.s, s.s, nn.i
  ;
  nn = 0
  While nn < n
    x = Hex(PeekA(p+nn),#PB_Ascii)
    x = RSet(x,2,"0")
    nn = nn+1
    If nn < n
      s = s+x+"."
    Else
      s = s+x
    EndIf
  Wend
  ProcedureReturn s
EndProcedure

Procedure.i filetimetodate(*ft.FILETIME)                             ; convert windows file timestamp to pb's date format
  Protected ft2.FILETIME, st.SYSTEMTIME
  ;
  FileTimeToLocalFileTime_(*ft,ft2)
  FileTimeToSystemTime_(ft2,st)
  ProcedureReturn Date(st\wYear,st\wMonth,st\wDay,st\wHour,st\wMinute,st\wSecond)
EndProcedure

Procedure.s GetShellLinkTargetPath(shellLinkFilePath$)
  Protected result.s = Space(#MAX_PATH + 1)
  Protected linkFile.IPersistFile
  Protected shellLink.IShellLinkW
  Protected IconIndexInFile.l
  ;
  ; this section is by AZJIO from the PureBasic forum
  ;
  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
  ;
  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(@result, #MAX_PATH, 0, 0)
          Debug "path "+result
          shellLink\getIconLocation(@result, #MAX_PATH, @IconIndexInFile)
          ; Debug IconIndexInFile
          Debug "icon "+result
        EndIf
      EndIf
      LinkFile\Release()
    EndIf
    shellLink\Release()
  EndIf
  ;
  CoUninitialize_()
  ;
  ProcedureReturn result
EndProcedure

Procedure main()
  Protected file.s
  Protected size.i
  Protected shelllinkheader.shelllinkheader
  Protected l.i, n.i, s.s, q.i
  Protected buffer_p.i, buffer_hnd.i
  ;
    file = "d:\PureBasic 64.lnk"
    file = "C:\Users\Admin\Desktop\Programming\PureBasic 64.lnk"
    file = "d:\WallX Rounded random.lnk"
    ;
  With shelllinkheader
    ;
    ReadFile(1,file,#PB_Ascii)
    ;
    ; a .lnk file always starts with a shelllinkheader of 76 bytes
    ;
    ; interesting links
    ;
    ;   - https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-shllink/c3376b21-0931-45e4-b2fc-a48ac0e60d15
    ;   - https://helgeklein.com/blog/dissecting-a-shortcut/
    ;
    ReadData(1,@shelllinkheader,76)
    ;
    ; some data retrieved
    ;
    Debug "size $"+peekhex(@\headersize,4)
    Debug "linkclsid %"+peekhex(@\linkclsid,16)
    Debug "last access "+FormatDate("%dd.%mm.%yyyy %hh:%ii:%ss",filetimetodate(@\accesstime))
    ;
    ; linkflags is 32 bits, definining any optional componets of the .lnk file
    ;
    Debug "linkflags %"+RSet(Bin(\linkflags,#PB_Long),32,"0")
    Debug "as admin %00000000000000000110000011110011"
    Debug "not admin %00000000000000000100000011110011"
    ;
    ; linkflags bit 0 - 1 - A - linktargetidlist - variable size, first 2 bytes contain size
    ;
    If (\linkflags & 1)
      l = ReadWord(1)
      Debug "A linktargetidlist "+Str(l)+" bytes"
      n = 0
      While n < l
        ReadByte(1)
        n = n+1
      Wend
    EndIf
    ;
    ; linkflags bit 1 - 2 - B - linkinfo - variable size, first 4 bytes contain size
    ;
    If (\linkflags & 2)
      l = ReadLong(1)
      Debug "B linkinfo "+Str(l)+" bytes"
      n = 0
      While n < l-4
        ReadByte(1)
        n = n+1
      Wend
    EndIf
    ;
    ; linkflags bit 2 - 4 - C - name - stringdata structure, first 2 bytes contain size in characters (unicode)
    ;
    If (\linkflags & 4)
      l = ReadWord(1)*2
      n = 0
      While n < l-2
        ReadByte(1)
        n = n+1
      Wend
      Debug "C name "+Str(l)+" bytes"
    EndIf
    ;
    ; linkflags bit 3 - 8 - D - relativepath
    ;
    If (\linkflags & 8)
      l = ReadWord(1)
      n = 0
      s = ""
      While n < l
        s = s+Chr(ReadWord(1))
        n = n+1
      Wend
      Debug "D relative path "+Str(l)+" bytes "+s
    EndIf
    ;
    ; linkflags bit 4 - 16 - E - working dir
    ;
    If (\linkflags & 16)
      l = ReadWord(1)
      n = 0
      s = ""
      While n < l
        s = s+Chr(ReadWord(1))
        n = n+1
      Wend
      Debug "E working dir "+Str(l)+" bytes "+s
    EndIf
    ;
    ; linkflags bit 5 - 32 - F - arguments
    ;
    If (\linkflags & 32)
      l = ReadWord(1)
      n = 0
      s = ""
      While n < l
        s = s+Chr(ReadWord(1))
        n = n+1
      Wend
      Debug "F arguments "+Str(l)+" bytes "+s
    EndIf
    ;
    ; linkflags bit 6 - 64 - G - iconlocation
    ;
    If (\linkflags & 64)
      l = ReadWord(1)
      n = 0
      s = ""
      While n < l
        s = s+Chr(ReadWord(1))
        n = n+1
      Wend
      Debug "G iconlocation "+Str(l)+" bytes "+s
    EndIf
    ;
    ; linkflags bit 13 - 8192 - N - runasuser - application is run as a different user
    ;
    If (\linkflags & 8192)
      Debug "run as admin"
    Else
      Debug "run as user"
    EndIf
    ;
    CloseFile(1)
  EndWith
  ;
  ; try azjio's code
  ;
  Debug ""
  GetShellLinkTargetPath(file)
  ;
EndProcedure
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
AZJIO
Addict
Addict
Posts: 1318
Joined: Sun May 14, 2017 1:48 am

Re: Retrieve icon (link / filename) from a .LNK file

Post by AZJIO »

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
User avatar
Mijikai
Addict
Addict
Posts: 1360
Joined: Sun Sep 11, 2016 2:17 pm

Re: Retrieve icon (link / filename) from a .LNK file

Post by Mijikai »

Do you only need the icon handle/image?

Code:

Code: Select all

EnableExplicit

UsePNGImageEncoder()

Procedure.i GetIcon(Path.s)
  Protected fileinfo.SHFILEINFO
  Protected image.i
  SHGetFileInfo_(Path,#FILE_ATTRIBUTE_NORMAL,@fileinfo,SizeOf(SHFILEINFO),#SHGFI_USEFILEATTRIBUTES|#SHGFI_ICON)
  If fileinfo\hIcon
    image = CreateImage(#PB_Any,32,32,32)
    If image
      If StartDrawing(ImageOutput(image))
        DrawingMode(#PB_2DDrawing_AllChannels)
        DrawImage(fileinfo\hIcon,0,0,32,32)
        StopDrawing()
      Else
        FreeImage(image)
        image = #Null
      EndIf
    EndIf
    DestroyIcon_(fileinfo\hIcon)
  EndIf
  ProcedureReturn image
EndProcedure

Debug GetIcon("XYZ.lnk");<- returns the icon as image

End
AZJIO
Addict
Addict
Posts: 1318
Joined: Sun May 14, 2017 1:48 am

Re: Retrieve icon (link / filename) from a .LNK file

Post by AZJIO »

Code: Select all

EnableExplicit

Procedure.i GetIcon(Path.s)
	Protected fileinfo.SHFILEINFO
	SHGetFileInfo_(Path,#FILE_ATTRIBUTE_NORMAL,@fileinfo,SizeOf(SHFILEINFO),#SHGFI_USEFILEATTRIBUTES|#SHGFI_ICON)
	ProcedureReturn fileinfo\hIcon
EndProcedure

Define himg = GetIcon( "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\7-Zip\7-Zip File Manager.lnk")

If OpenWindow(0, 0, 0, 220, 100, "Example...", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)
	ButtonImageGadget(1, 10, 10, 40, 40, himg)
    Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf
Your code is hard to read, here's a screenshot
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6161
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Retrieve icon (link / filename) from a .LNK file

Post by blueznl »

Originally I was only looking for the icon, but I got puzzled on the internals. The shell functions listed above work well for most .LNK files, so I stick to those. There are a few cases where they don't find the right info.

The few cases are pretty rare. Some very old .LNK files, some .LNK files created by old pre-Win10 software, and some Metro apps give either no icon, no executable, or both. Sometimes, when you 'toggle' the 'runasadmin' link in the properties of a .LNK, it drops the executable path. Then there are .LNK's with a relative path that is stripped on some occasions.

I've based my code on the stuff that you posted above, and I'm fine for now :-) Those few rare cases are not important enough to cover, thx again!
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: Retrieve icon (link / filename) from a .LNK file

Post by BarryG »

blueznl wrote: Sat Oct 02, 2021 5:24 pmsometimes it manages to find the proper destination, but I found a few cases it would not, where Windows would still manage to launch the program
What type of program does the LNK file launch? Because if it's a Win 10 UWP program, then the LNK file won't have the literal path in it.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6161
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Retrieve icon (link / filename) from a .LNK file

Post by blueznl »

BarryG wrote: Sun Oct 03, 2021 3:06 am
blueznl wrote: Sat Oct 02, 2021 5:24 pmsometimes it manages to find the proper destination, but I found a few cases it would not, where Windows would still manage to launch the program
What type of program does the LNK file launch? Because if it's a Win 10 UWP program, then the LNK file won't have the literal path in it.
Any and all kinds. I now use a workaround:

.LNK's that do not return a target I'll launch by calling that lnk with 'RunProgram("uwp_metroshit.lnk').

The other stuff I take apart for the different fields.

Like I said, some older software create their own funny desktop shortcuts, non NWP. But I think some of that code is WinXP, or even earlier :-)
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
BarryG
Addict
Addict
Posts: 3292
Joined: Thu Apr 18, 2019 8:17 am

Re: Retrieve icon (link / filename) from a .LNK file

Post by BarryG »

blueznl wrote: Mon Oct 04, 2021 12:01 am.LNK's that do not return a target I'll launch by calling that lnk with 'RunProgram("uwp_metroshit.lnk').
Good thinking! I like it.
AZJIO
Addict
Addict
Posts: 1318
Joined: Sun May 14, 2017 1:48 am

Re: Retrieve icon (link / filename) from a .LNK file

Post by AZJIO »

blueznl
As I understand it, your function reads a shortcut. Can you make a function to create a shortcut? The fact is that using WinAPI the function of the function checks the existence of a file and icons, so when generating a couple of hundreds of shortcuts is noticeable braking.
User avatar
blueznl
PureBasic Expert
PureBasic Expert
Posts: 6161
Joined: Sat May 17, 2003 11:31 am
Contact:

Re: Retrieve icon (link / filename) from a .LNK file

Post by blueznl »

You mean by directly WRITING the shortcut file?

Yeah, that's actually not that hard. If you look at one of the earlier posts, I tried to deduct the .LNK format, you can simply create your own .LNK files using that format.
( PB6.00 LTS Win11 x64 Asrock AB350 Pro4 Ryzen 5 3600 32GB GTX1060 6GB)
( The path to enlightenment and the PureBasic Survival Guide right here... )
Post Reply