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

如何在PowerShell中获取支持Unicode与长路径的快捷方式目标?

读取含长路径/Unicode字符的.lnk快捷方式目标路径的解决方案

现有方法的局限性

方法1:WScript.Shell COM对象

原采纳答案的代码:

$Shell = New-Object -ComObject WScript.Shell
$Target = $Shell.CreateShortcut('<full-path-to-shortcut>').TargetPath

存在的问题:

  • 快捷方式文件路径过长时,无法读取该文件
  • 目标路径包含中日韩等Unicode字符时,返回结果会变成???
  • 快捷方式路径本身包含Unicode字符时,无法创建快捷方式对象

方法2:Win32_ShortcutFile WMI类

获赞较少的替代方案代码:

$Path = '<full-path-to-shortcut>' -replace "\\", "\\\\"
$ShortcutFile = Get-WmiObject Win32_ShortcutFile -Filter "name = '$Path'"
$Target = $ShortcutFile.Target

存在的问题:

  • 不支持网络UNC路径(如\\Server\Share\Shortcut.lnk)
  • 不支持带UNC限定符的路径(如\\?\UNC\Server\Share\Shortcut.lnk)

可行解决方案

方案1:直接解析.lnk二进制结构

.lnk文件有固定二进制格式,通过读取二进制内容提取目标路径,完全支持长路径和Unicode:

function Get-ShortcutTarget {
    param(
        [Parameter(Mandatory=$true)]
        [string]$ShortcutPath
    )

    # 处理长路径,添加\\?\前缀绕过260字符限制
    if (-not $ShortcutPath.StartsWith("\\?\")) {
        if ($ShortcutPath.StartsWith("\\")) {
            $ShortcutPath = "\\?\UNC\" + $ShortcutPath.Substring(2)
        } else {
            $ShortcutPath = "\\?\" + $ShortcutPath
        }
    }

    $bytes = [System.IO.File]::ReadAllBytes($ShortcutPath)
    $targetOffset = [System.BitConverter]::ToUInt32($bytes, 0x14)
    $targetLength = [System.BitConverter]::ToUInt16($bytes, 0x1C)
    $targetBytes = $bytes[($targetOffset + 0x4C)..($targetOffset + 0x4C + $targetLength - 1)]
    $targetPath = [System.Text.UnicodeEncoding]::Unicode.GetString($targetBytes)

    # 还原长路径格式
    if ($targetPath.StartsWith("\\")) {
        $targetPath = "\\?\UNC\" + $targetPath.Substring(2)
    } else {
        $targetPath = "\\?\" + $targetPath
    }

    return $targetPath
}

# 使用示例
Get-ShortcutTarget -ShortcutPath "C:\长路径测试\包含Unicode字符的快捷方式.lnk"

说明:

  • 借助\\?\长路径前缀突破Windows传统路径长度限制
  • 直接读取.lnk二进制内容提取Unicode编码的目标路径,完美兼容中日韩等字符
  • 支持本地长路径、UNC网络路径

方案2:调用系统原生API

通过调用shell32.dll的SHGetShortcutTargetWAPI,配合长路径前缀实现需求:

Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;

public class ShortcutHelper {
    [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
    private static extern int SHGetShortcutTargetW(IntPtr hWnd, string pszShortcut, IntPtr pszTarget, ref int cchTarget);

    public static string GetShortcutTarget(string shortcutPath) {
        int bufferSize = 2048;
        IntPtr targetBuffer = Marshal.AllocHGlobal(bufferSize * 2);
        try {
            int result = SHGetShortcutTargetW(IntPtr.Zero, shortcutPath, targetBuffer, ref bufferSize);
            if (result == 0) {
                return Marshal.PtrToStringUni(targetBuffer);
            } else {
                throw new System.ComponentModel.Win32Exception(result);
            }
        } finally {
            Marshal.FreeHGlobal(targetBuffer);
        }
    }
}
"@

function Get-LnkTarget {
    param(
        [Parameter(Mandatory=$true)]
        [string]$Path
    )

    # 处理长路径
    if (-not $Path.StartsWith("\\?\")) {
        $Path = $Path -replace "^\\\\", "\\?\UNC\"
        if (-not $Path.StartsWith("\\?\")) {
            $Path = "\\?\" + $Path
        }
    }

    return [ShortcutHelper]::GetShortcutTarget($Path)
}

# 使用示例
Get-LnkTarget -Path "\\Server\Share\超长路径\Unicode快捷方式.lnk"

说明:

  • 调用系统原生API,兼容性更强
  • 同样依赖\\?\前缀处理长路径
  • 部分受限环境下可能需要管理员权限

验证说明

即使系统已启用长路径支持,WScript.Shell的CreateShortcut方法仍会截断目标路径(最长仅246字符),而上述两种方案可以完整提取超长路径的目标内容,同时完美支持Unicode字符。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 10:35:56