从PathTooLongException检索路径信息



我正在使用.Net 4.0中的DirectoryInfo和FileInfo来枚举目录树中的文件,并点击PathTooLongException。简化版本低于

public static class Test
{
    public static void Search(DirectoryInfo base)
    {
        foreach(var file in base.GetFiles())
        {
            try
            {
                Console.WriteLine(file.FullName);
            } catch(PathTooLongException ex)
            {
                // What path was this?
            }
        }
        foreach(var dir in base.GetDirectories())
        {
            Search(dir);
        }
    }
}

当抛出错误时,我想知道是什么文件路径导致了问题。显然,我不能要求FullName,因为这就是错误所在。我可以从file.Name获得名称,但如果我不能获得路径的其余部分,因为file.Directory会给出PathTooLongException,即使从中找到文件的DirectoryInfo工作得很好!(但我不能使用它,因为实际的代码要复杂得多)。

查看堆栈跟踪,它似乎使用了一个内部路径(我在调试中看到了一个受保护的file.FullPath),并试图从完整(超大)路径中删除该目录。大多数问题似乎都涉及System.IO.Path.NormalizePath,我听说在.Net 4.0中进行了一些更改。我没有尝试过以前版本的框架。

我的问题:

  1. 如何从这个异常中获取完整路径;它似乎是在没有任何有用信息的情况下通过的
  2. 为什么框架需要限制路径中的字符来截断文件名

提前感谢您的帮助,
Andy

除了使用反射,或者使用库或p/Invoke来使用支持长路径和手动检查长度的Windows API之外,我想不出其他方法了。完整路径存储在名为FullPathprotected string字段中

foreach(var dir in new DirectoryInfo (@"D:longpaths")
                     .GetFileSystemInfos("*.*", SearchOption.AllDirectories))
{
    try
    {
        Console.WriteLine(dir.FullName);
    }
    catch (PathTooLongException)
    {
                FieldInfo fld = typeof(FileSystemInfo).GetField(
                                        "FullPath", 
                                         BindingFlags.Instance | 
                                         BindingFlags.NonPublic);
                Console.WriteLine(fld.GetValue(dir));  // outputs your long path
    }
}

如果您试图实际处理文件,而不仅仅是检查文件长度,我建议使用微软BCL团队的类似库,但它不会创建DirectoryInfosFileInfoFileSystemInfo,只会创建字符串。因此,它可能不会取代您的代码。

至于你第二个问题的答案,我建议你阅读这篇关于.NET中长路径的博客文章。这是其中的一句话,解释了为什么他们没有迅速在.NET中添加长路径支持。

很少有人抱怨32K的限制,所以,问题解决了吗?不完全是。我们过去不愿意添加长路径有几个原因,以及为什么我们仍然对此很谨慎,这与安全性、\?\的Windows API中不一致的支持有关语法和应用程序兼容性。

这是一个由三部分组成的系列,解释了为什么API是这样的,以及为什么存在限制。

最新更新