使用GetLongPathName获取已删除文件长路径失败,如何解决?
已删除文件短路径转长路径的解决方案
GetLongPathName依赖文件系统中存在的实体,因此当文件或文件夹被删除后,它无法解析对应的短路径,只能返回空字符串。以下是几种可行的处理方案:
1. 提前缓存短-长路径映射(最可靠)
在文件存在时主动捕获并存储短路径与长路径的对应关系,当FileSystemWatcher触发删除事件时,直接从缓存中读取对应的长路径。
实现示例
// 全局缓存:短路径(不区分大小写)到长路径的映射 private static readonly Dictionary<string, string> _pathCache = new(StringComparer.OrdinalIgnoreCase); // 获取并缓存长路径(文件存在时调用) public static string CacheLongPath(string shortPath) { if (_pathCache.TryGetValue(shortPath, out var longPath)) return longPath; var sb = new StringBuilder(256); int result = GetLongPathName(shortPath, sb, sb.Capacity); if (result > 0 && result <= sb.Capacity) { longPath = sb.ToString(); _pathCache[shortPath] = longPath; // 递归缓存父目录的短-长路径映射,避免子项删除后父目录仍存在的情况 var parentDir = Path.GetDirectoryName(longPath); if (!string.IsNullOrEmpty(parentDir)) { var parentShortSb = new StringBuilder(256); GetShortPathName(parentDir, parentShortSb, parentShortSb.Capacity); var parentShortPath = parentShortSb.ToString(); _pathCache[parentShortPath] = parentDir; } return longPath; } return shortPath; } // 补充GetShortPathName的P/Invoke声明 [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public static extern int GetShortPathName( [MarshalAs(UnmanagedType.LPTStr)] string path, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder shortPath, int shortPathLength);
注意事项
- 需在文件创建、重命名等事件触发时同步更新缓存,保证映射关系准确。
- 可定期清理缓存中过期的条目(比如根据文件最后修改时间),避免内存占用过高。
2. 解析Windows 8.3短命名规则(有限适用)
Windows短路径遵循8.3命名规则:取长名前6个字符加~N(N为递增数字,解决重名),后缀保留前3个字符。但这种方法有明显局限性:
- 无法区分重名条目(如
FIRSTF~1和FIRSTF~2对应的长名无法仅通过规则确定) - 非ASCII字符(如中文)的短名是经过转换的,无法还原原长名
- 需逐层解析父目录,若父目录已删除且未缓存,无法继续解析
3. 枚举父目录回溯(父目录存在时可用)
如果被删除文件的父目录仍存在,可调用FindFirstFile枚举父目录下的所有条目,匹配短路径对应的长名。若父目录也已删除,此方法失效。
内容的提问来源于stack exchange,提问作者H44R
相关产品推荐
相关产品推荐

