Reading the target of a .lnk file in Python?

I know this is an older thread but I feel that there isn't much information on the method that uses the link specification as noted in the original question.

My shortcut target implementation could not use the win32com module and after a lot of searching, decided to come up with my own. Nothing else seemed to accomplish what I needed under my restrictions. Hopefully this will help other folks in this same situation.

It uses the binary structure Microsoft has provided for MS-SHLLINK.

import struct

path = 'myfile.txt.lnk'    
target = ''

with open(path, 'rb') as stream:
    content = stream.read()
    # skip first 20 bytes (HeaderSize and LinkCLSID)
    # read the LinkFlags structure (4 bytes)
    lflags = struct.unpack('I', content[0x14:0x18])[0]
    position = 0x18
    # if the HasLinkTargetIDList bit is set then skip the stored IDList 
    # structure and header
    if (lflags & 0x01) == 1:
        position = struct.unpack('H', content[0x4C:0x4E])[0] + 0x4E
    last_pos = position
    position += 0x04
    # get how long the file information is (LinkInfoSize)
    length = struct.unpack('I', content[last_pos:position])[0]
    # skip 12 bytes (LinkInfoHeaderSize, LinkInfoFlags, and VolumeIDOffset)
    position += 0x0C
    # go to the LocalBasePath position
    lbpos = struct.unpack('I', content[position:position+0x04])[0]
    position = last_pos + lbpos
    # read the string at the given position of the determined length
    size= (length + last_pos) - position - 0x02
    temp = struct.unpack('c' * size, content[position:position+size])
    target = ''.join([chr(ord(a)) for a in temp])

Create a shortcut using Python (via WSH)

import sys
import win32com.client 

shell = win32com.client.Dispatch("WScript.Shell")
shortcut = shell.CreateShortCut("t:\\test.lnk")
shortcut.Targetpath = "t:\\ftemp"
shortcut.save()


Read the Target of a Shortcut using Python (via WSH)

import sys
import win32com.client 

shell = win32com.client.Dispatch("WScript.Shell")
shortcut = shell.CreateShortCut("t:\\test.lnk")
print(shortcut.Targetpath)

Alternatively, you could try using SHGetFolderPath(). The following code might work, but I'm not on a Windows machine right now so I can't test it.

import ctypes

shell32 = ctypes.windll.shell32

# allocate MAX_PATH bytes in buffer
video_folder_path = ctypes.create_string_buffer(260)

# 0xE is CSIDL_MYVIDEO
# 0 is SHGFP_TYPE_CURRENT
# If you want a Unicode path, use SHGetFolderPathW instead
if shell32.SHGetFolderPathA(None, 0xE, None, 0, video_folder_path) >= 0:
    # success, video_folder_path now contains the correct path
else:
    # error

Basically call the Windows API directly. Here is a good example found after Googling:

import os, sys
import pythoncom
from win32com.shell import shell, shellcon

shortcut = pythoncom.CoCreateInstance (
  shell.CLSID_ShellLink,
  None,
  pythoncom.CLSCTX_INPROC_SERVER,
  shell.IID_IShellLink
)
desktop_path = shell.SHGetFolderPath (0, shellcon.CSIDL_DESKTOP, 0, 0)
shortcut_path = os.path.join (desktop_path, "python.lnk")
persist_file = shortcut.QueryInterface (pythoncom.IID_IPersistFile)
persist_file.Load (shortcut_path)

shortcut.SetDescription ("Updated Python %s" % sys.version)
mydocs_path = shell.SHGetFolderPath (0, shellcon.CSIDL_PERSONAL, 0, 0)
shortcut.SetWorkingDirectory (mydocs_path)

persist_file.Save (shortcut_path, 0)

This is from http://timgolden.me.uk/python/win32_how_do_i/create-a-shortcut.html.

You can search for "python ishelllink" for other examples.

Also, the API reference helps too: http://msdn.microsoft.com/en-us/library/bb774950(VS.85).aspx