Esempio n. 1
0
        // This is where the magic happens - returns one result per result target framework
        private IEnumerable <AnalyzerResult> BuildTargets(BuildEnvironment buildEnvironment, string targetFramework, string[] targetsToBuild, bool analyze)
        {
            using (AnonymousPipeLoggerServer pipeLogger = new AnonymousPipeLoggerServer())
            {
                using (EventProcessor eventProcessor = new EventProcessor(ProjectFile.Path, Loggers, pipeLogger, analyze))
                {
                    // Get the filename
                    string fileName         = buildEnvironment.MsBuildExePath;
                    string initialArguments = string.Empty;
                    if (Path.GetExtension(buildEnvironment.MsBuildExePath).Equals(".dll", StringComparison.OrdinalIgnoreCase))
                    {
                        // .NET Core MSBuild .dll needs to be run with dotnet
                        fileName         = "dotnet";
                        initialArguments = $"\"{buildEnvironment.MsBuildExePath}\"";
                    }

                    // Get the arguments to use
                    string loggerPath     = typeof(PipeLogger).Assembly.Location;
                    string loggerArgument = $"/l:{nameof(PipeLogger)},{FormatArgument(loggerPath)};{pipeLogger.GetClientHandle()}";
                    Dictionary <string, string> effectiveGlobalProperties = GetEffectiveGlobalProperties(buildEnvironment);
                    if (!string.IsNullOrEmpty(targetFramework))
                    {
                        // Setting the TargetFramework MSBuild property tells MSBuild which target framework to use for the outer build
                        effectiveGlobalProperties[MsBuildProperties.TargetFramework] = targetFramework;
                    }
                    string propertyArgument = effectiveGlobalProperties.Count == 0 ? string.Empty : $"/property:{(string.Join(";", effectiveGlobalProperties.Select(x => $"{x.Key}={FormatArgument(x.Value)}")))}";
                    string targetArgument   = targetsToBuild == null || targetsToBuild.Length == 0 ? string.Empty : $"/target:{string.Join(";", targetsToBuild)}";
                    string arguments        = $"{initialArguments} /noconsolelogger /nodeReuse:False {targetArgument} {propertyArgument} {loggerArgument} {FormatArgument(ProjectFile.Path)}";

                    int exitCode;
                    using (ProcessRunner processRunner = new ProcessRunner(fileName, arguments, Path.GetDirectoryName(ProjectFile.Path), GetEffectiveEnvironmentVariables(buildEnvironment), Manager.ProjectLogger))
                    {
                        // Start MSBuild
                        processRunner.Start();

                        // Read the pipe
                        InterlockedBool exit   = new InterlockedBool(false);
                        AutoResetEvent  exited = new AutoResetEvent(false);
                        Thread          thread = new Thread(() =>
                        {
                            while (pipeLogger.Read() && !exit)
                            {
                            }
                            exited.Set();
                        })
                        {
                            IsBackground = true
                        };
                        thread.Start();

                        // Wait for MSBuild to finish and then wait for pipe closure
                        exitCode = processRunner.WaitForExit();
                        exit.Set();
                        exited.WaitOne();
                    }

                    return(exitCode != 0 ? Array.Empty <AnalyzerResult>() : eventProcessor.GetResults(this));
                }
            }
        }
        public void AnonymousPipeSupportsCancellation()
        {
            // Given
            BuildEventArgs buildEvent = null;

            using (CancellationTokenSource tokenSource = new CancellationTokenSource())
            {
                using (AnonymousPipeLoggerServer server = new AnonymousPipeLoggerServer(tokenSource.Token))
                {
                    // When
                    tokenSource.CancelAfter(1000);  // The call to .Read() below will block so need to set a timeout for cancellation
                    buildEvent = server.Read();
                }
            }

            // Then
            buildEvent.ShouldBeNull();
        }