4

I am using Directory.GetDirectories() with a Linq statement to loop through all directories in a folder that aren't system folders, however I am discovering a bunch of bad ReparsePoints in the folder, which is causing the method to take a long time as it times out on each bad reparse point.

The code I am currently using looks like this:

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

I have also tried using code like this for testing, but it also hangs for a full minute or so on the bad folders:

foreach (var item in dir.GetDirectories("*", SearchOption.TopDirectoryOnly))
{
    Console.WriteLine(item.Name);
    Console.WriteLine(item.Attributes);
}

It should be noted that the above bit of code works fine in .Net 4.0, but in 3.5 it will hang for a minute on each bad reparse point.

Trying to open these folders manually in Windows Explorer results in a "Network Path Not Found" error.

Is there another way to loop through good subfolders inside a folder that doesn't use the Attributes property, or that bypasses the bad reparse points?

I have already tried using Directory.Exists(), and that is equally slow.

Rachel
  • 130,264
  • 66
  • 304
  • 490
  • I have found that streaming the input from a process is virtually the same performance-wise and requires no exception handling and is actually more robust and reliable. Strange but true (at least for me it's true) – Gayot Fow Sep 18 '13 at 22:32
  • @Rachel, have you tried just excluding `FileAttributes.ReparsePoint` from search with your `Where` clause? – noseratio Sep 20 '13 at 04:15
  • 2
    @Noseratio Yes, accessing the `FileAttributes` property causes the performance problem. – Rachel Sep 20 '13 at 12:56
  • This may be a silly question - but did you try putting the FileAttributes.ReparsePoint exclusion as the first check in your where clause? i.e. .Where(d => ((d.Attributes & FileAttributes.ReparsePoint) != FileAttributes.Reparsepoint) && ((d.Attributes & FileAttributes.Hidden) != FileAttributes.Hidden) && ((d.Attributes & FileAttributes.System) != FileAttributes.System)) – Sean Hosey Sep 20 '13 at 13:26
  • 1
    @SeanHosey Yes, accessing the `FileAttributes` property is what causes the problem since the directory doesn't actually exist, so when it tries to check it to see if it contains `ReparsePoint` or any other value, it takes about a full minute to figure out the `FileAttributes` property of the bad reparse point. – Rachel Sep 20 '13 at 14:15

1 Answers1

0

According to this answer: *FASTEST* directory listing

For the best performance, it is possible to P/Invoke NtQueryDirectoryFile, documented as ZwQueryDirectoryFile

From MSDN: FILE_REPARSE_POINT_INFORMATION structure

This information can be queried in either of the following ways:

Call ZwQueryDirectoryFile, passing FileReparsePointInformation as the value of FileInformationClass and passing a caller-allocated, FILE_REPARSE_POINT_INFORMATION-structured buffer as the value of FileInformation.

Create an IRP with major function code IRP_MJ_DIRECTORY_CONTROL and minor function code IRP_MN_QUERY_DIRECTORY.

Community
  • 1
  • 1
sehe
  • 374,641
  • 47
  • 450
  • 633