public async Task Run(CollectionConfiguration config)
        {
            bool rootExists = Directory.Exists(config.RootDirectory);

            if (!rootExists)
            {
                throw new ArgumentException($"Could not locate directory: {config.RootDirectory}");
            }

            if (!Directory.Exists(this.GetPerProjectOutputPath()))
            {
                Directory.CreateDirectory(this.GetPerProjectOutputPath());
            }
            this.ClearExistingOutputFiles();

            List <Task> metricsCollectionTasks = new List <Task>();

            this.Traverse(new DirectoryInfo(config.RootDirectory), config, metricsCollectionTasks);

            await Task.WhenAll(metricsCollectionTasks);

            this.statusUpdater("Completed reading all projects.");

            var metrics = await MetricsCompiler.CompileFromDirectory(this.GetPerProjectOutputPath());

            var resultsPath = this.GetResultsPath();

            CompletedMetricsHandler.WriteMetrics(metrics, resultsPath);
            this.statusUpdater($"Wrote results to {resultsPath}.");
        }
        private string GetPerProjectOutputFile(string csProjPath, CollectionConfiguration config)
        {
            var    smallerPath = csProjPath.Substring(config.RootDirectory.Length); // Strip out the leading path, i.e. remove "C:\myProjects\" from "C:\myProjects\project1.csproj"
            string escapedPath = smallerPath
                                 .Replace(Path.DirectorySeparatorChar, '_')
                                 .Replace(":", "_")
                                 .Replace(".", "_");

            var fullOutputPath = Path.Combine(this.GetPerProjectOutputPath(), escapedPath + ".xml");

            return(fullOutputPath);
        }
 private async Task CollectMetricsAsync(string projPath, CollectionConfiguration config)
 {
     if (config.CollectionMethod == CollectionMethod.ProjectNuGet)
     {
         await this.CollectMetricsMsBuildAsync(projPath, config);
     }
     else if (config.CollectionMethod == CollectionMethod.ProvidedMetricsExe)
     {
         await this.CollectMetricsWithIncludedMetricsExeAsync(projPath, config);
     }
     else
     {
         throw new ArgumentException($"Unrecognized CollectionMethod value: {config.CollectionMethod}");
     }
 }
        public void Traverse(DirectoryInfo currentDirectory, CollectionConfiguration config, List <Task> tasks)
        {
            foreach (string file in Directory.EnumerateFiles(currentDirectory.ToString()))
            {
                if (file.ToLower().EndsWith("." + CsProjExtension))
                {
                    tasks.Add(
                        this.throttler.Throttle(
                            async() => { await this.CollectMetricsAsync(file, config); }
                            )
                        );
                }
            }

            foreach (var childDirectory in currentDirectory.EnumerateDirectories())
            {
                this.Traverse(childDirectory, config, tasks);
            }
        }
        private async Task CollectMetricsMsBuildAsync(string projPath, CollectionConfiguration config)
        {
            var exe  = Path.Combine(config.MsBuildPath, MsBuildExe);
            var args = $"/t:Metrics /p:MetricsOutputFile={this.GetPerProjectOutputFile(projPath, config)} {projPath}";

            // running from NuGet ex - msbuild /t:Metrics /p:MetricsOutputFile=<filename>
            ProcessStartInfo psi = new ProcessStartInfo(MsBuildExe);

            psi.Arguments              = args;
            psi.UseShellExecute        = false;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError  = true;

            var p = new Process();

            p.StartInfo           = psi;
            p.OutputDataReceived += P_OutputDataReceived;
            p.ErrorDataReceived  += P_ErrorDataReceived;
            p.Start();

            await p.WaitForExitAsync();

            this.statusUpdater($"Gathered metrics for {projPath}.");
        }