internal static extern Boolean FindNextFile(SafeFindFileHandle hFindFile, out WIN32_FIND_DATA lpFindFileData);
/// <summary> /// The main method that does the recursive file matching. /// </summary> /// <param name="directory"> /// The file directory to search. /// </param> /// <remarks> /// This method calls the low level Windows API because the built in .NET APIs do not /// support long file names. (Those greater than 260 characters). /// </remarks> static private void RecurseFiles(String directory) { String lookUpdirectory = String.Empty; if (directory.StartsWith(@"\\", StringComparison.OrdinalIgnoreCase)) { lookUpdirectory += directory.Replace(@"\\", @"\\?\UNC\") + "\\*"; } else { lookUpdirectory = "\\\\?\\" + directory + "\\*"; } NativeMethods.WIN32_FIND_DATA w32FindData; using (SafeFindFileHandle fileHandle = NativeMethods.FindFirstFileEx(lookUpdirectory, NativeMethods.FINDEX_INFO_LEVELS.Basic, out w32FindData, NativeMethods.FINDEX_SEARCH_OPS.SearchNameMatch, IntPtr.Zero, NativeMethods.FindExAdditionalFlags.LargeFetch)) { if (!fileHandle.IsInvalid) { do { // Does this match "." or ".."? If so get out. if ((w32FindData.cFileName.Equals(".", StringComparison.OrdinalIgnoreCase) || (w32FindData.cFileName.Equals("..", StringComparison.OrdinalIgnoreCase)))) { continue; } // Is this a directory? If so, queue up another task. if ((w32FindData.dwFileAttributes & FileAttributes.Directory) == FileAttributes.Directory) { Interlocked.Increment(ref totalDirectories); String subDirectory = Path.Combine(directory, w32FindData.cFileName); if (Options.IncludeDirectories) { if (IsNameMatch(subDirectory)) { Interlocked.Increment(ref totalMatches); QueueConsoleWriteLine(subDirectory); } } // Recurse our way to happiness.... Task.Factory.StartNew(() => RecurseFiles(subDirectory), TaskCreationOptions.AttachedToParent); } else { // It's a file so look at it. Interlocked.Increment(ref totalFiles); Int64 fileSize = w32FindData.nFileSizeLow + ((Int64)w32FindData.nFileSizeHigh << 32); Interlocked.Add(ref totalSize, fileSize); String fullFile = directory; if (!directory.EndsWith("\\", StringComparison.OrdinalIgnoreCase)) { fullFile += "\\"; } fullFile += w32FindData.cFileName; String matchName = fullFile; if (false == Options.IncludeDirectories) { matchName = w32FindData.cFileName; } if (IsNameMatch(matchName)) { Interlocked.Increment(ref totalMatches); Interlocked.Add(ref totalMatchesSize, fileSize); QueueConsoleWriteLine(fullFile); } } } while (NativeMethods.FindNextFile(fileHandle, out w32FindData)); } } }
internal static extern Boolean FindNextFile(SafeFindFileHandle hFindFile, out WIN32_FIND_DATA lpFindFileData);