Shortcuts are actually far more complex than most people realize even after dealing with the IShellLink interface. The really technical bits are hidden behind a whole other interface: IShellLinkDataList.
Windows shortcuts and shortcuts placed by some programs allow the path to refer to a special location that might vary: for example, the Windows Media Player start menu shortcut on Windows 7 was actually created with a target of %ProgramFiles(x86)%\Windows Media Player\wmplayer.exe. Whether you click it, load its properties page, or call IShellLink's GetPath, the special Program Files reference will be expanded. But what if you want to see that original reference? Here I bring another article from the wonderful Old New Thing blog to VB6. As part of the code, you can also see all the SLDF_ flags associated with a link.
Requirements
-Windows XP or higher
-oleexp 3.51 or newer (released with this code on 9 May 2016; 3.5 will NOT work); oleexp3.tlb must be added under Project-References, but it's an IDE-only requirement- the typelib does not need to be distributed with the compiled EXE.
The Code
(Note: I tried copying directly into the struct by passing tEXP or trying ByVal VarPtr(tEXP); but both resulted in the value of the memory pointer being shoved into the .cbSize member.)Code:Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) Public Sub ShowLinkInfo(sLink As String) 'sLink must include .lnk suffix (hidden even when 'show extensions' is enabled) 'e.g. C:\folder\Shortcut to MyProgram.exe.lnk Dim psdi As IShellLinkDataList Dim pLNK As ShellLinkW Dim ppf As IPersistFile Set pLNK = New ShellLinkW Set ppf = pLNK ppf.Load sLink, STGM_READ Set psdi = pLNK Dim dwFlg As SHELL_LINK_DATA_FLAGS psdi.GetFlags dwFlg Debug.Print "flags=" & Hex$(dwFlg) If (dwFlg And SLDF_HAS_EXP_SZ) Then Debug.Print "has exp_sz" Dim tEXP As EXP_SZ_LINK Dim ltPtr As Long psdi.CopyDataBlock EXP_SZ_LINK_SIG, ltPtr If ltPtr Then Debug.Print "got non-zero ptr" CopyMemory tEXP, ByVal ltPtr, LenB(tEXP) Debug.Print "struct size=" & tEXP.cbSize & ",sig=" & Hex$(tEXP.dwSignature) Debug.Print "str=" & WCHARtoSTR(tEXP.swzTarget) Else Debug.Print "no ptr to tEXP" End If Else Debug.Print "no flag match" End If End Sub Public Function WCHARtoSTR(aCh() As Integer) As String Dim i As Long Dim sz As String For i = LBound(aCh) To UBound(aCh) If aCh(i) <> 0 Then sz = sz & ChrW(CLng(aCh(i))) End If Next WCHARtoSTR = sz End Function
You can set flags and add/delete data blocks as well, look for a far more advanced demo of this interface in the future.




Reply With Quote
