You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Windows超长路径下如何获取快捷方式的目标路径?

解决Windows超长路径下提取快捷方式目标路径的问题

你碰到的问题本质是WScript.Shell的CreateShortCut方法不支持超过260字符的超长路径——哪怕你后来给目标路径加了\\?\前缀,也没法解决打开lnk文件本身时的路径长度限制,因为第一步调用CreateShortCut就已经失败了。

下面给你两种可行的解决方案:

方法一:调用Windows原生API(通过ctypes实现)

Windows系统提供了专门处理快捷方式的原生API,能直接支持超长路径。我们可以用Python的ctypes库调用这些API,绕开WScript.Shell的限制。

示例代码如下:

import ctypes
from ctypes import wintypes

# 定义API所需的结构体
class SHORTCUTTARGETINFO(ctypes.Structure):
    _fields_ = [
        ('cbSize', wintypes.DWORD),
        ('pwszTarget', wintypes.LPWSTR),
        ('cchTarget', wintypes.DWORD),
        ('pwszArguments', wintypes.LPWSTR),
        ('cchArguments', wintypes.DWORD),
        ('pwszWorkingDirectory', wintypes.LPWSTR),
        ('cchWorkingDirectory', wintypes.DWORD),
        ('dwFlags', wintypes.DWORD),
        ('dwHotkey', wintypes.DWORD),
        ('dwShowCmd', wintypes.DWORD),
        ('hIcon', wintypes.HICON),
        ('pwszIconLocation', wintypes.LPWSTR),
        ('cchIconLocation', wintypes.DWORD),
    ]

# 加载shell32.dll并绑定API
shell32 = ctypes.WinDLL('shell32', use_last_error=True)
SHGetShortcutTargetInfoW = shell32.SHGetShortcutTargetInfoW
SHGetShortcutTargetInfoW.argtypes = [wintypes.LPCWSTR, ctypes.POINTER(SHORTCUTTARGETINFO)]
SHGetShortcutTargetInfoW.restype = wintypes.BOOL

def get_lnk_target(lnk_path):
    # 给lnk路径添加超长路径前缀,确保Windows能识别
    if not lnk_path.startswith('\\\\?\\'):
        lnk_path = '\\\\?\\' + lnk_path
    
    # 初始化结构体
    sti = SHORTCUTTARGETINFO()
    sti.cbSize = ctypes.sizeof(SHORTCUTTARGETINFO)
    
    # 第一次调用获取缓冲区大小
    if not SHGetShortcutTargetInfoW(lnk_path, ctypes.byref(sti)):
        error = ctypes.get_last_error()
        if error == 0x7A:  # 错误码:缓冲区不足
            # 分配足够的缓冲区空间
            sti.cchTarget += 1
            sti.pwszTarget = ctypes.create_unicode_buffer(sti.cchTarget)
            # 第二次调用获取目标路径
            if SHGetShortcutTargetInfoW(lnk_path, ctypes.byref(sti)):
                return sti.pwszTarget.value
        raise ctypes.WinError(error)
    return sti.pwszTarget.value

# 使用示例
fp = r'C:\very_long_path\to\a\link\file\shortcut.lnk'
target_path = get_lnk_target(fp)
print(target_path)

方法二:直接解析LNK文件的二进制结构

如果不想依赖系统API,也可以直接解析lnk文件的二进制格式(微软已公开LNK文件的规范)。这种方法完全靠读取文件内容提取目标路径,不需要调用任何Windows COM组件。

简化版示例代码(仅处理本地文件快捷方式):

import struct

def parse_lnk_target(lnk_path):
    # 处理超长路径,确保能正常打开文件
    if not lnk_path.startswith('\\\\?\\'):
        lnk_path = '\\\\?\\' + lnk_path
    
    with open(lnk_path, 'rb') as f:
        # 跳过文件头前20字节
        f.seek(20)
        # 读取标志位,判断是否包含目标路径列表
        flags = struct.unpack('<I', f.read(4))[0]
        has_link_target_id_list = (flags & 0x01) != 0
        
        if not has_link_target_id_list:
            return None
        
        # 跳转到LinkTargetIDList区域
        f.seek(0x4C)
        id_list_size = struct.unpack('<H', f.read(2))[0]
        f.seek(2, 1)  # 跳过IDList的空起始项
        
        # 解析Shell Item列表,提取文件路径
        path_parts = []
        remaining = id_list_size - 2
        while remaining > 0:
            item_size = struct.unpack('<H', f.read(2))[0]
            remaining -= item_size
            item_data = f.read(item_size - 2)
            
            # 识别文件系统类型的Shell Item
            if item_data[0] == 0x31:
                # 提取UTF-16编码的路径片段
                path = item_data[1:].decode('utf-16le').rstrip('\x00')
                path_parts.append(path)
        
        return '\\'.join(path_parts)

# 使用示例
fp = r'C:\very_long_path\to\a\link\file\shortcut.lnk'
target_path = parse_lnk_target(fp)
print(target_path)

注意事项

  • 方法一中的API仅支持Windows Vista及以上系统;
  • 方法二的简化版只适配本地文件快捷方式,若需处理网络共享、特殊文件夹的快捷方式,需要扩展解析逻辑;
  • 两种方法都需要给lnk文件路径添加\\?\前缀,这是Windows识别超长路径的必要条件。

内容的提问来源于stack exchange,提问作者user2366975

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:14:49