public static IEnumerable <string> FindRevitFiles(
            string folderPath,
            SearchOption searchOption,
            RevitFileType revitFileType,
            bool ignoreRevitBackups,
            Func <string, bool> progressReporter
            )
        {
            var searchFilePattern = ALL_FILES_WITH_AN_EXTENSION_PATTERN;

            if (revitFileType == RevitFileType.Project)
            {
                searchFilePattern = REVIT_PROJECT_FILE_PATTERN;
            }
            else if (revitFileType == RevitFileType.Family)
            {
                searchFilePattern = REVIT_FAMILY_FILE_PATTERN;
            }
            else if (revitFileType == RevitFileType.ProjectAndFamily)
            {
                searchFilePattern = ALL_FILES_WITH_AN_EXTENSION_PATTERN;
            }

            var foldersToScan = Enumerable.Empty <string>();

            if (searchOption == SearchOption.AllDirectories)
            {
                foldersToScan = (
                    new[] { folderPath }
                    .Concat(PathUtil.SafeEnumerateFolders(folderPath, "*", SearchOption.AllDirectories))
                    );
            }
            else
            {
                foldersToScan = new[] { folderPath };
            }

            var revitFilePaths = new List <string>();

            foreach (var folderToScan in foldersToScan)
            {
                bool cancelled = progressReporter(folderToScan);

                if (cancelled)
                {
                    break;
                }

                revitFilePaths.AddRange(
                    PathUtil.SafeEnumerateFiles(folderToScan, searchFilePattern, SearchOption.TopDirectoryOnly)
                    .Where(filePath => HasRevitFileExtension(filePath, ignoreRevitBackups))
                    );
            }

            return(revitFilePaths);
        }
        public static List <string[]> FindAndExtractRevitFilesInfoWithProgressReporting(
            string baseFolderPath,
            SearchOption searchOption,
            RevitFileType revitFileType,
            bool expandNetworkPaths,
            bool extractRevitVersionInfo,
            bool ignoreRevitBackupFiles,
            Func <string, bool> progressReporter
            )
        {
            var infoRows = new List <string[]>();

            progressReporter("Scanning for Revit files ...");

            var revitFilePaths = FindRevitFiles(baseFolderPath, searchOption, revitFileType, ignoreRevitBackupFiles, progressReporter);

            int numberOfRevitFilePaths = revitFilePaths.Count();

            bool cancelled = progressReporter(string.Empty);

            if (!cancelled)
            {
                if (expandNetworkPaths)
                {
                    string expandingNetworkPathsMessagePrefix = "Expanding network paths";

                    var indexedExpandedRevitFilePaths =
                        PathUtil.EnumerateExpandedFullNetworkPaths(revitFilePaths)
                        .Select((revitFilePath, index) => Tuple.Create(index, revitFilePath));

                    var expandedRevitFilePaths = new List <string>();

                    foreach (var indexedExpandedRevitFilePath in indexedExpandedRevitFilePaths)
                    {
                        int    index = indexedExpandedRevitFilePath.Item1;
                        string expandedRevitFilePath = indexedExpandedRevitFilePath.Item2;

                        progressReporter(expandingNetworkPathsMessagePrefix + " (" + (index + 1).ToString() + " of " + numberOfRevitFilePaths.ToString() + ") ...");

                        expandedRevitFilePaths.Add(expandedRevitFilePath);
                    }

                    revitFilePaths = expandedRevitFilePaths;
                }

                infoRows = revitFilePaths.Select(revitFilePath => new[] { revitFilePath }).ToList();

                if (extractRevitVersionInfo)
                {
                    string extractingNetworkPathsMessagePrefix = "Extracting Revit files version information";

                    var indexedRevitVersionTexts =
                        PathUtil.EnumerateRevitVersionTexts(revitFilePaths)
                        .Select((revitFilePath, index) => Tuple.Create(index, revitFilePath));

                    var allRevitVersionTexts = new List <string[]>();

                    foreach (var indexedRevitVersionText in indexedRevitVersionTexts)
                    {
                        int      index             = indexedRevitVersionText.Item1;
                        string[] revitVersionTexts = indexedRevitVersionText.Item2;

                        progressReporter(extractingNetworkPathsMessagePrefix + " (" + (index + 1).ToString() + " of " + numberOfRevitFilePaths.ToString() + ") ...");

                        allRevitVersionTexts.Add(revitVersionTexts);
                    }

                    infoRows = (
                        revitFilePaths
                        .Zip(
                            allRevitVersionTexts,
                            (revitFilePath, revitVersionTexts) => new[] { revitFilePath, revitVersionTexts[0], revitVersionTexts[1] }
                            )
                        .ToList()
                        );
                }
            }

            return(infoRows);
        }