在 .Net 3.5 中使用 GetDirectories() 识别错误的 ReparsePoints?

Posted

技术标签:

【中文标题】在 .Net 3.5 中使用 GetDirectories() 识别错误的 ReparsePoints?【英文标题】:Identifying bad ReparsePoints with GetDirectories() in .Net 3.5? 【发布时间】:2013-09-16 01:19:35 【问题描述】:

我正在使用带有 Linq 语句的 Directory.GetDirectories() 循环遍历文件夹中不是系统文件夹的所有目录,但是我在文件夹中发现了一堆错误的 ReparsePoints,这导致该方法采用很长一段时间,因为它在每个错误的重解析点上超时。

我目前使用的代码是这样的:

subdirectories = directory.GetDirectories("*", SearchOption.TopDirectoryOnly)
    .Where(d => ((d.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden)
         && ((d.Attributes & FileAttributes.System) != FileAttributes.System));

我也尝试过使用这样的代码进行测试,但它也会在坏文件夹上挂起整整一分钟左右:

foreach (var item in dir.GetDirectories("*", SearchOption.TopDirectoryOnly))

    Console.WriteLine(item.Name);
    Console.WriteLine(item.Attributes);

需要注意的是,上述代码在 .Net 4.0 中运行良好,但在 3.5 中,它会在每个错误的重解析点挂起一分钟。

尝试在 Windows 资源管理器中手动打开这些文件夹会导致“找不到网络路径”错误。

是否有另一种方法可以遍历不使用 Attributes 属性的文件夹中的好子文件夹,或者绕过错误的重解析点?

我已经尝试过使用Directory.Exists(),但速度同样慢。

【问题讨论】:

我发现流式传输来自进程的输入在性能方面几乎相同,不需要异常处理,实际上更健壮和可靠。奇怪但真实(至少对我来说是真实的) @Rachel,您是否尝试过使用您的 Where 子句从搜索中排除 FileAttributes.ReparsePoint @Noseratio 是的,访问FileAttributes 属性会导致性能问题。 这可能是一个愚蠢的问题 - 但您是否尝试将 FileAttributes.ReparsePoint 排除作为第一个检查放在 where 子句中?即 .Where(d => ((d.​​Attributes & FileAttributes.ReparsePoint) != FileAttributes.Reparsepoint) && ((d.​​Attributes & FileAttributes.Hidden) != FileAttributes.Hidden) && ((d.​​Attributes & FileAttributes.System ) != FileAttributes.System)) @SeanHosey 是的,访问FileAttributes 属性是导致问题的原因,因为该目录实际上并不存在,所以当它尝试检查它是否包含ReparsePoint 或任何其他值,大约需要整整一分钟才能找出错误重解析点的 FileAttributes 属性。 【参考方案1】:

根据这个答案:*FASTEST* directory listing

为了获得最佳性能,可以 P/Invoke NtQueryDirectoryFile,记录为 ZwQueryDirectoryFile

来自 MSDN:FILE_REPARSE_POINT_INFORMATION structure

可以通过以下任一方式查询该信息:

调用ZwQueryDirectoryFile,将FileReparsePointInformation 作为FileInformationClass 的值传递,并将调用者分配的FILE_REPARSE_POINT_INFORMATION 结构化缓冲区作为FileInformation 的值传递。

使用主要功能代码IRP_MJ_DIRECTORY_CONTROL和次要功能代码IRP_MN_QUERY_DIRECTORY创建一个IRP。

【讨论】:

以上是关于在 .Net 3.5 中使用 GetDirectories() 识别错误的 ReparsePoints?的主要内容,如果未能解决你的问题,请参考以下文章

我可以在 .Net 3.5 项目中使用任务并行库吗?

在 .NET 3.5 中使用反射生成子类列表

在 SSIS 2005 的脚本任务中引用 .net 3.5 程序集?

在 .Net 3.5 中使用 GetDirectories() 识别错误的 ReparsePoints?

如何在 .NET 3.5 项目中引用 .NET 4.0 程序集

在 .Net 3.5 中使用动态关键字