Get the Shortcut target

Just starting out? Need help? Post your questions and find answers here.
Little John
Addict
Addict
Posts: 4786
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Get the Shortcut target

Post by Little John »

Hello infratec,

many thanks for your code! The function GetLinkTarget() is exactly what I was looking for.
Although the code is rather old, it seems to work almost flawlessly here on my system with the current PB version 5.73 LTS on Windows 10. :-)
But because newer PB versions always create Unicode programs, two lines have to be changed:

In both codes that you posted, replace

Code: Select all

Target$ = PeekS(*Buffer + *LinkInfo\LocalBasePathOffset)
Target$ + PeekS(*Buffer + *LinkInfo\CommonPathSuffixOffset)
with

Code: Select all

Target$ = PeekS(*Buffer + *LinkInfo\LocalBasePathOffset, -1, #PB_Ascii)
Target$ + PeekS(*Buffer + *LinkInfo\CommonPathSuffixOffset, -1, #PB_Ascii)
This seems to work even with targets that contain German umlauts.

Thanks again!
Little John
Addict
Addict
Posts: 4786
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: Get the Shortcut target

Post by Little John »

Unfortunately, I encountered problems when checking the links in my start menu with GetLinkTarget().
My computer is pretty new, I did not mess with any start menu entries, and all links in the start menu work as expected when I click at them. So the error messages by GetLinkTarget() are wrong. Here are some examples (PB 5.73 LTS (x64) on Windows 10):
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Character Map.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Math Input Panel.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Notepad.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Paint.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Quick Assist.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Remote Desktop Connection.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Snipping Tool.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Steps Recorder.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Windows Fax and Scan.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Windows Media Player.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\Wordpad.lnk has no LinkInfo

Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Büro\LibreOffice 7.1\LibreOffice (abgesicherter Modus).lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Büro\LibreOffice 7.1\LibreOffice Base.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Büro\LibreOffice 7.1\LibreOffice Calc.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Büro\LibreOffice 7.1\LibreOffice Draw.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Büro\LibreOffice 7.1\LibreOffice Impress.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Büro\LibreOffice 7.1\LibreOffice Math.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Büro\LibreOffice 7.1\LibreOffice Writer.lnk has no LinkInfo
Error: C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Büro\LibreOffice 7.1\LibreOffice.lnk has no LinkInfo
AZJIO
Addict
Addict
Posts: 2183
Joined: Sun May 14, 2017 1:48 am

Re: Get the Shortcut target

Post by AZJIO »

infratec wrote: Sat Aug 21, 2010 6:52 pm A first result out of the above documentation: LnkInfo.pb
Can you create a shortcut using structures? The native function makes checks for the existence of file targets, so by creating several dozen shortcuts, it works very slowly, for more than two minutes, which it should do instantly.
BarryG
Addict
Addict
Posts: 4168
Joined: Thu Apr 18, 2019 8:17 am

Re: Get the Shortcut target

Post by BarryG »

I have a shortcut file ("d:\shortcut.lnk") that points to IrfanView with a command-line argument. Can the following code be made to show the command-line part as well as the target executable? Thanks.

Image

Code: Select all

Structure ShellLinkHeaderStr
  HeaderSize.l
  LinkCLSID.a[16]
  LinkFlags.l
  FileAttributes.l
  CreationTime.q
  AccessTime.q
  WriteTime.q
  FileSize.l
  IconIndex.l
  ShowCommand.l
  HotKey.w
  Reserved1.w
  Reserved2.l
  Reserved3.l
EndStructure

Structure LinkInfoStr
  LinkInfoSize.l
  LinkInfoHeaderSize.l
  LinkInfoFlags.l
  VolumeIDOffset.l
  LocalBasePathOffset.l
  CommonNetworkRelativeLinkOffset.l
  CommonPathSuffixOffset.l
  LocalBasePathOffsetUnicode.l
  CommonPathSuffixOffsetUnicode.l
EndStructure


Enumeration ; neccessary LinkFlags
  #HasLinkTargetIDList
  #HasLinkInfo
EndEnumeration


Procedure.s GetLinkTarget(FileName$)
  
  If ReadFile(0, Filename$)
    
    Define ByteLengthW.w, ByteLengthL.l, CharLength.w
    
    ReadData(0, @ByteLengthL, 4)
    FileSeek(0, 0)
    *Header = AllocateMemory(ByteLengthL)
    If ReadData(0, *Header, ByteLengthL) = ByteLengthL
      
      *ShellLinkHeader.ShellLinkHeaderStr = *Header
      
      If *ShellLinkHeader\LinkFlags & (1 << #HasLinkTargetIDList)
        ReadData(0, @ByteLengthW, 2)
        ; skip the LinkTargetIDList for now
        FileSeek(0, Loc(0) + ByteLengthW)
      EndIf
      
      Pos = Loc(0)
      
      If *ShellLinkHeader\LinkFlags & (1 << #HasLinkInfo)
        ReadData(0, @BytelengthL, 4)
        If ByteLengthL > 0
          FileSeek(0, Pos)
          *Buffer = AllocateMemory(ByteLengthL)
          If ReadData(0, *Buffer, ByteLengthL) = ByteLengthL
            *LinkInfo.LinkInfoStr = *Buffer
            Target$ = PeekS(*Buffer + *LinkInfo\LocalBasePathOffset, -1, #PB_Ascii)
            Target$ + PeekS(*Buffer + *LinkInfo\CommonPathSuffixOffset, -1, #PB_Ascii)
          Else
            Target$ = "Error: A fault occured"
          EndIf
          FreeMemory(*Buffer)
        EndIf
      Else
        Target$ = "Error: " + Filename$ + " has no LinkInfo"
      EndIf
      
    EndIf
    
    FreeMemory(*Header)
    CloseFile(0)
  Else
    Target$ = "Error: Was not able to open " + Filename$
  EndIf
  
  ProcedureReturn Target$
  
EndProcedure

Debug GetLinkTarget("d:\shortcut.lnk") ; Want: "D:\[Apps]\IrfanView\i_view64.exe D:\Sunset.jpg"
AZJIO
Addict
Addict
Posts: 2183
Joined: Sun May 14, 2017 1:48 am

Re: Get the Shortcut target

Post by AZJIO »

BarryG wrote: Thu May 29, 2025 10:59 am Can the following code be made to show the command-line part
viewtopic.php?p=331770#p331770

Code: Select all

EnableExplicit

#Version = "1.06"

Structure ShellLinkHeaderStr
	HeaderSize.l
	LinkCLSID.a[16]
	LinkFlags.l
	FileAttributes.l
	CreationTime.q
	AccessTime.q
	WriteTime.q
	FileSize.l
	IconIndex.l
	ShowCommand.l
	HotKey.w
	Reserved1.w
	Reserved2.l
	Reserved3.l
EndStructure

Enumeration ; LinkFlags
	#HasLinkTargetIDList
	#HasLinkInfo
	#HasName
	#HasRelativePath
	#HasWorkingDir
	#HasArguments
	#HasIconLocation
	#IsUnicode
	#ForceNoLinkInfo
	#HasExpString
	#RunInSeparateProcess
	#Unused1
	#HasDarwinID
	#RunAsUser
	#HasExpIcon
	#NoPidAlias
	#Unused2
	#RunWithShimLayer
	#ForceNoLinkTrack
	#EnableTargetMetadata
	#DisableLinkPathTracking
	#DisableKnownFolderTracking
	#DisableKnownFolderAlias
	#AllowLinkToLink
	#UnaliasOnSave
	#PreferEnvironmentPath
	#KeepLocalIDListForUNCTarget
EndEnumeration


Structure LinkInfoStr
	LinkInfoSize.l
	LinkInfoHeaderSize.l
	LinkInfoFlags.l
	VolumeIDOffset.l
	LocalBasePathOffset.l
	CommonNetworkRelativeLinkOffset.l
	CommonPathSuffixOffset.l
	LocalBasePathOffsetUnicode.l
	CommonPathSuffixOffsetUnicode.l
EndStructure

Structure LocalVolumeTableStr
	Length.l
	TypeOfVolume.l
	VolumeSerialNumber.l
	OffsetOfVolumeName.l
EndStructure

Procedure.s GetLinkTarget(FileName$)
	Protected *Header, Pos, Target$, *Buffer, UniCode, PeekSFlag
	Protected *ShellLinkHeader.ShellLinkHeaderStr
	Protected *LinkInfo.LinkInfoStr

; 	Filename$ = "C:\PB\PureBasic_x64-.lnk"

	If ReadFile(0, Filename$)

		Define ByteLengthW.w, ByteLengthL.l, CharLength.w

		ReadData(0, @ByteLengthL, 4)
		FileSeek(0, 0)
		*Header = AllocateMemory(ByteLengthL)
		If ReadData(0, *Header, ByteLengthL) = ByteLengthL

			*ShellLinkHeader.ShellLinkHeaderStr = *Header

			If *ShellLinkHeader\LinkFlags & (1 << #HasLinkTargetIDList)
				ReadData(0, @ByteLengthW, 2)
				; skip the LinkTargetIDList for now
				FileSeek(0, Loc(0) + ByteLengthW)
			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #IsUnicode)
				UniCode = #True
				PeekSFlag = #PB_Unicode
			Else
				UniCode = #False
				PeekSFlag = #PB_Ascii
			EndIf

			Pos = Loc(0)

			If *ShellLinkHeader\LinkFlags & (1 << #HasLinkInfo)
				ReadData(0, @BytelengthL, 4)
				If ByteLengthL > 0
					FileSeek(0, Pos)
					*Buffer = AllocateMemory(ByteLengthL)
					If ReadData(0, *Buffer, ByteLengthL) = ByteLengthL
						*LinkInfo.LinkInfoStr = *Buffer
						Target$ = PeekS(*Buffer + *LinkInfo\LocalBasePathOffset, - 1, #PB_Ascii)
						Target$ + PeekS(*Buffer + *LinkInfo\CommonPathSuffixOffset, - 1, #PB_Ascii)
					Else
						Debug "Error: Target"
					EndIf
					FreeMemory(*Buffer)
				EndIf
			Else
				Target$ = "Error: " + Filename$ + " has no LinkInfo"
			EndIf



; 			If *ShellLinkHeader\LinkFlags & (1 << #HasName)
; 				ReadData(0, @ByteLengthW, 2)
; 				*Buffer = AllocateMemory(ByteLengthW)
; 				If ReadData(0, *Buffer, ByteLengthW) = ByteLengthW
; 					Debug ("Description: " + PeekS(*Buffer))
; 				Else
; 					End 3
; 				EndIf
; 				FreeMemory(*Buffer)
; 			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #HasRelativePath)
				ReadData(0, @CharLength, 2)
				If UniCode
					ByteLengthW = CharLength * 2
				Else
					ByteLengthW = CharLength
				EndIf
				*Buffer = AllocateMemory(ByteLengthW)
				If ReadData(0, *Buffer, ByteLengthW) = ByteLengthW
; 					Debug ("RelativePath: " + PeekS(*Buffer, CharLength, PeekSFlag))
				Else
					Debug "Error: RelativePath"
				EndIf
				FreeMemory(*Buffer)
			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #HasWorkingDir)
				ReadData(0, @CharLength, 2)
				If UniCode
					ByteLengthW = CharLength * 2
				Else
					ByteLengthW = CharLength
				EndIf
				*Buffer = AllocateMemory(ByteLengthW)
				If ReadData(0, *Buffer, ByteLengthW) = ByteLengthW
; 					Debug ("WorkingDirectory: " + PeekS(*Buffer, CharLength, PeekSFlag))
				Else
					Debug "Error: WorkingDirectory"
				EndIf
				FreeMemory(*Buffer)
			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #HasArguments)
				ReadData(0, @CharLength, 2)
				If UniCode
					ByteLengthW = CharLength * 2
				Else
					ByteLengthW = CharLength
				EndIf
				*Buffer = AllocateMemory(ByteLengthW)
				If ReadData(0, *Buffer, ByteLengthW) = ByteLengthW
; 					Debug ("CommandlineArguments: " + PeekS(*Buffer, CharLength, PeekSFlag))
					Debug Target$ + " " + PeekS(*Buffer, CharLength, PeekSFlag)
				Else
					Debug "Error: CommandlineArguments"
				EndIf
				FreeMemory(*Buffer)
			EndIf


      ; there is more stuff, but not interresting for now.
		Else
			End 1
		EndIf
		FreeMemory(*Header)
		CloseFile(0)
	Else
		Debug ("Was not able to open " + Filename$)
	EndIf
EndProcedure

Debug GetLinkTarget("d:\shortcut.lnk")
BarryG
Addict
Addict
Posts: 4168
Joined: Thu Apr 18, 2019 8:17 am

Re: Get the Shortcut target

Post by BarryG »

Thank you so much AZJIO and Infratec! :)
AZJIO
Addict
Addict
Posts: 2183
Joined: Sun May 14, 2017 1:48 am

Re: Get the Shortcut target

Post by AZJIO »

Code: Select all

EnableExplicit

#Version = "1.06"

Structure ShellLinkHeaderStr
	HeaderSize.l
	LinkCLSID.a[16]
	LinkFlags.l
	FileAttributes.l
	CreationTime.q
	AccessTime.q
	WriteTime.q
	FileSize.l
	IconIndex.l
	ShowCommand.l
	HotKey.w
	Reserved1.w
	Reserved2.l
	Reserved3.l
EndStructure

Enumeration ; LinkFlags
	#HasLinkTargetIDList
	#HasLinkInfo
	#HasName
	#HasRelativePath
	#HasWorkingDir
	#HasArguments
	#HasIconLocation
	#IsUnicode
	#ForceNoLinkInfo
	#HasExpString
	#RunInSeparateProcess
	#Unused1
	#HasDarwinID
	#RunAsUser
	#HasExpIcon
	#NoPidAlias
	#Unused2
	#RunWithShimLayer
	#ForceNoLinkTrack
	#EnableTargetMetadata
	#DisableLinkPathTracking
	#DisableKnownFolderTracking
	#DisableKnownFolderAlias
	#AllowLinkToLink
	#UnaliasOnSave
	#PreferEnvironmentPath
	#KeepLocalIDListForUNCTarget
EndEnumeration


Structure LinkInfoStr
	LinkInfoSize.l
	LinkInfoHeaderSize.l
	LinkInfoFlags.l
	VolumeIDOffset.l
	LocalBasePathOffset.l
	CommonNetworkRelativeLinkOffset.l
	CommonPathSuffixOffset.l
	LocalBasePathOffsetUnicode.l
	CommonPathSuffixOffsetUnicode.l
EndStructure

Structure LocalVolumeTableStr
	Length.l
	TypeOfVolume.l
	VolumeSerialNumber.l
	OffsetOfVolumeName.l
EndStructure

Procedure.s GetLinkTargetParam(FileName$, *Error.Integer)
	Protected *Header, Pos, *Buffer, UniCode, PeekSFlag, fid, Error, Result$
	Protected *ShellLinkHeader.ShellLinkHeaderStr
	Protected *LinkInfo.LinkInfoStr
	Protected ByteLengthW.w, ByteLengthL.l, CharLength.w

; 	Filename$ = "C:\PB\PureBasic_x64-.lnk"
	fid = ReadFile(#PB_Any, Filename$)
	If fid

		ReadData(fid, @ByteLengthL, 4)
		FileSeek(fid, 0)
		*Header = AllocateMemory(ByteLengthL)
		If ReadData(fid, *Header, ByteLengthL) = ByteLengthL

			*ShellLinkHeader.ShellLinkHeaderStr = *Header

			If *ShellLinkHeader\LinkFlags & (1 << #HasLinkTargetIDList)
				ReadData(fid, @ByteLengthW, 2)
				; skip the LinkTargetIDList for now
				FileSeek(fid, Loc(fid) + ByteLengthW)
			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #IsUnicode)
				UniCode = #True
				PeekSFlag = #PB_Unicode
			Else
				UniCode = #False
				PeekSFlag = #PB_Ascii
			EndIf

			Pos = Loc(fid)

			If *ShellLinkHeader\LinkFlags & (1 << #HasLinkInfo)
				ReadData(fid, @BytelengthL, 4)
				If ByteLengthL > 0
					FileSeek(fid, Pos)
					*Buffer = AllocateMemory(ByteLengthL)
					If ReadData(fid, *Buffer, ByteLengthL) = ByteLengthL
						*LinkInfo.LinkInfoStr = *Buffer
						Result$ = PeekS(*Buffer + *LinkInfo\LocalBasePathOffset, - 1, #PB_Ascii)
						Result$ + PeekS(*Buffer + *LinkInfo\CommonPathSuffixOffset, - 1, #PB_Ascii)
					Else
						*Error\i | 1
						Debug "Error: Target"
					EndIf
					FreeMemory(*Buffer)
				EndIf
			Else
				*Error\i | 2
				Debug "Error: " + Filename$ + " has no LinkInfo"
			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #HasName)
				ReadData(fid, @ByteLengthW, 2)
				Pos = Loc(fid)
				FileSeek(fid, Pos + ByteLengthW)
			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #HasRelativePath)
				ReadData(fid, @ByteLengthW, 2)
				If UniCode
					ByteLengthW * 2
				EndIf
				Pos = Loc(fid)
				FileSeek(fid, Pos + ByteLengthW)
			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #HasWorkingDir)
				ReadData(fid, @ByteLengthW, 2)
				If UniCode
					ByteLengthW * 2
				EndIf
				Pos = Loc(fid)
				FileSeek(fid, Pos + ByteLengthW)
			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #HasArguments)
				ReadData(fid, @CharLength, 2)
				If UniCode
					ByteLengthW = CharLength * 2
				Else
					ByteLengthW = CharLength
				EndIf
				*Buffer = AllocateMemory(ByteLengthW)
				If ReadData(fid, *Buffer, ByteLengthW) = ByteLengthW
					Result$ + " " + PeekS(*Buffer, CharLength, PeekSFlag)
				Else
					*Error\i | 4
					Debug "Error: CommandlineArguments"
				EndIf
				FreeMemory(*Buffer)
			EndIf

		Else
			*Error\i | 8
			Debug "Error: Header"
		EndIf
		FreeMemory(*Header)
		CloseFile(fid)
	Else
		*Error\i | 16
		Debug "Was not able to open " + Filename$
	EndIf
	If Not Error
		ProcedureReturn Result$
	EndIf
EndProcedure

Define Error
Debug GetLinkTarget("d:\shortcut.lnk", @Error)
Debug "Error: " + Error
BarryG
Addict
Addict
Posts: 4168
Joined: Thu Apr 18, 2019 8:17 am

Re: Get the Shortcut target

Post by BarryG »

I celebrated too soon. :( The code works great if I manually specify the LNK file in code, but it doesn't work with OpenFileRequester() because it just returns the EXE without the command-line parts. Any way around that?

Code: Select all

EnableExplicit

#Version = "1.06"

Structure ShellLinkHeaderStr
	HeaderSize.l
	LinkCLSID.a[16]
	LinkFlags.l
	FileAttributes.l
	CreationTime.q
	AccessTime.q
	WriteTime.q
	FileSize.l
	IconIndex.l
	ShowCommand.l
	HotKey.w
	Reserved1.w
	Reserved2.l
	Reserved3.l
EndStructure

Enumeration ; LinkFlags
	#HasLinkTargetIDList
	#HasLinkInfo
	#HasName
	#HasRelativePath
	#HasWorkingDir
	#HasArguments
	#HasIconLocation
	#IsUnicode
	#ForceNoLinkInfo
	#HasExpString
	#RunInSeparateProcess
	#Unused1
	#HasDarwinID
	#RunAsUser
	#HasExpIcon
	#NoPidAlias
	#Unused2
	#RunWithShimLayer
	#ForceNoLinkTrack
	#EnableTargetMetadata
	#DisableLinkPathTracking
	#DisableKnownFolderTracking
	#DisableKnownFolderAlias
	#AllowLinkToLink
	#UnaliasOnSave
	#PreferEnvironmentPath
	#KeepLocalIDListForUNCTarget
EndEnumeration


Structure LinkInfoStr
	LinkInfoSize.l
	LinkInfoHeaderSize.l
	LinkInfoFlags.l
	VolumeIDOffset.l
	LocalBasePathOffset.l
	CommonNetworkRelativeLinkOffset.l
	CommonPathSuffixOffset.l
	LocalBasePathOffsetUnicode.l
	CommonPathSuffixOffsetUnicode.l
EndStructure

Structure LocalVolumeTableStr
	Length.l
	TypeOfVolume.l
	VolumeSerialNumber.l
	OffsetOfVolumeName.l
EndStructure

Procedure.s GetLinkTarget(FileName$)
	Protected *Header, Pos, Target$, *Buffer, UniCode, PeekSFlag
	Protected *ShellLinkHeader.ShellLinkHeaderStr
	Protected *LinkInfo.LinkInfoStr

; 	Filename$ = "C:\PB\PureBasic_x64-.lnk"

	If ReadFile(0, Filename$)

		Define ByteLengthW.w, ByteLengthL.l, CharLength.w

		ReadData(0, @ByteLengthL, 4)
		FileSeek(0, 0)
		*Header = AllocateMemory(ByteLengthL)
		If ReadData(0, *Header, ByteLengthL) = ByteLengthL

			*ShellLinkHeader.ShellLinkHeaderStr = *Header

			If *ShellLinkHeader\LinkFlags & (1 << #HasLinkTargetIDList)
				ReadData(0, @ByteLengthW, 2)
				; skip the LinkTargetIDList for now
				FileSeek(0, Loc(0) + ByteLengthW)
			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #IsUnicode)
				UniCode = #True
				PeekSFlag = #PB_Unicode
			Else
				UniCode = #False
				PeekSFlag = #PB_Ascii
			EndIf

			Pos = Loc(0)

			If *ShellLinkHeader\LinkFlags & (1 << #HasLinkInfo)
				ReadData(0, @BytelengthL, 4)
				If ByteLengthL > 0
					FileSeek(0, Pos)
					*Buffer = AllocateMemory(ByteLengthL)
					If ReadData(0, *Buffer, ByteLengthL) = ByteLengthL
						*LinkInfo.LinkInfoStr = *Buffer
						Target$ = PeekS(*Buffer + *LinkInfo\LocalBasePathOffset, - 1, #PB_Ascii)
						Target$ + PeekS(*Buffer + *LinkInfo\CommonPathSuffixOffset, - 1, #PB_Ascii)
					Else
						Debug "Error: Target"
					EndIf
					FreeMemory(*Buffer)
				EndIf
			Else
				Target$ = "Error: " + Filename$ + " has no LinkInfo"
			EndIf



; 			If *ShellLinkHeader\LinkFlags & (1 << #HasName)
; 				ReadData(0, @ByteLengthW, 2)
; 				*Buffer = AllocateMemory(ByteLengthW)
; 				If ReadData(0, *Buffer, ByteLengthW) = ByteLengthW
; 					Debug ("Description: " + PeekS(*Buffer))
; 				Else
; 					End 3
; 				EndIf
; 				FreeMemory(*Buffer)
; 			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #HasRelativePath)
				ReadData(0, @CharLength, 2)
				If UniCode
					ByteLengthW = CharLength * 2
				Else
					ByteLengthW = CharLength
				EndIf
				*Buffer = AllocateMemory(ByteLengthW)
				If ReadData(0, *Buffer, ByteLengthW) = ByteLengthW
; 					Debug ("RelativePath: " + PeekS(*Buffer, CharLength, PeekSFlag))
				Else
					Debug "Error: RelativePath"
				EndIf
				FreeMemory(*Buffer)
			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #HasWorkingDir)
				ReadData(0, @CharLength, 2)
				If UniCode
					ByteLengthW = CharLength * 2
				Else
					ByteLengthW = CharLength
				EndIf
				*Buffer = AllocateMemory(ByteLengthW)
				If ReadData(0, *Buffer, ByteLengthW) = ByteLengthW
; 					Debug ("WorkingDirectory: " + PeekS(*Buffer, CharLength, PeekSFlag))
				Else
					Debug "Error: WorkingDirectory"
				EndIf
				FreeMemory(*Buffer)
			EndIf

			If *ShellLinkHeader\LinkFlags & (1 << #HasArguments)
				ReadData(0, @CharLength, 2)
				If UniCode
					ByteLengthW = CharLength * 2
				Else
					ByteLengthW = CharLength
				EndIf
				*Buffer = AllocateMemory(ByteLengthW)
				If ReadData(0, *Buffer, ByteLengthW) = ByteLengthW
; 					Debug ("CommandlineArguments: " + PeekS(*Buffer, CharLength, PeekSFlag))
					Debug Target$ + " " + PeekS(*Buffer, CharLength, PeekSFlag)
				Else
					Debug "Error: CommandlineArguments"
				EndIf
				FreeMemory(*Buffer)
			EndIf


      ; there is more stuff, but not interresting for now.
		Else
			End 1
		EndIf
		FreeMemory(*Header)
		CloseFile(0)
	Else
		Debug ("Was not able to open " + Filename$)
	EndIf
EndProcedure

;Debug GetLinkTarget("d:\shortcut.lnk") ; Works great directly from code.
Debug GetLinkTarget(OpenFileRequester("Select LNK file","d:\","",0)) ; Doesn't when I select the LNK file.
AZJIO
Addict
Addict
Posts: 2183
Joined: Sun May 14, 2017 1:48 am

Re: Get the Shortcut target

Post by AZJIO »

It's not right.

Code: Select all

Define path$
path$ = OpenFileRequester("Select LNK file","D:\","",0)
Debug path$
It is right

Code: Select all

Define path$
path$ = OpenFileRequester("Select LNK file","D:\","lnk|*.lnk",0)
Debug path$
BarryG
Addict
Addict
Posts: 4168
Joined: Thu Apr 18, 2019 8:17 am

Re: Get the Shortcut target

Post by BarryG »

I want to get the shortcut target AND command line args like before, but it doesn't work with OpenFileRequester(), which doesn't make any sense. The same string is passed to the GetLinkTarget() procedure but if you use OpenFileRequester() to select the LNK file, it doesn't work. :shock: Maybe the compiler is overriding the LNK selection itself and getting the target file instead. Fred?
Post Reply