2012-03-06 154 views
3

我在.NET 4.0中使用DirectoryInfo和FileInfo来枚举目录树中的文件,并且遇到PathTooLongException。简化版本低于从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. 为什么框架需要限制路径中的字符来切断文件名?

在此先感谢您的帮助,
安迪

回答

6

我想不出任何其他方式又比使用反射,或使用图书馆或P/Invoke来使用其他我的头顶支持长路径并手动检查长度的Windows API。完整路径存储在protected string场称为FullPath

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 
    } 
} 

如果你想实际上做文件的东西,不能只检查文件的长度,我建议使用一个图书馆这样一个from the BCL team at Microsoft,但它不会创建DirectoryInfosFileInfoFileSystemInfo,只能是字符串。所以它可能不是你的代码的替代品。

至于你的第二个问题的答案,我建议阅读处理.NET中的长路径的this blog post。这是引用它的原因,它解释了为什么他们没有快速地在.NET中添加长路径支持。

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

这是一个由3部分组成的系列文章,解释了为什么API是这种方式以及为什么限制在那里的几个原因。

+0

谢谢克里斯托弗,我担心情况会如此。只是私下保留路径并且不允许在没有先验证它的情况下访问它,尽管它为我创建了无效路径就好了。 您指向的'LongPath'库看起来很棒!不幸的是,我忘了提及所有路径都是UNC,因此无法按原样使用(还)。通过代码来查看如何实现直接API会非常有用。 – Andyrooger 2012-03-07 09:49:35

+0

@Andyrooger,是的,我忘了那个。我分叉了代码,并在不久前添加了该代码。你可以在codeplex项目中获得代码(http://longpaths.codeplex.com/)。使用源代码,而不是发行版,我修复了一个愚蠢的错误。 – 2012-03-07 21:01:29

+0

@ChristopherCurrens +1 FieldInfo提示! – 2013-06-11 19:09:31