コード例 #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));
                }
            }
        }
コード例 #2
0
        public void SendsDataOverAnonymousPipe([ValueSource(nameof(MessageCounts))] int messageCount)
        {
            // Given
            List <BuildEventArgs> eventArgs = new List <BuildEventArgs>();
            int exitCode;

            using (AnonymousPipeLoggerServer server = new AnonymousPipeLoggerServer())
            {
                server.AnyEventRaised += (s, e) => eventArgs.Add(e);

                // When
                exitCode = RunClientProcess(server, server.GetClientHandle(), messageCount);
            }

            // Then
            exitCode.ShouldBe(0);
            eventArgs.Count.ShouldBe(messageCount + 1);
            eventArgs[0].ShouldBeOfType <BuildStartedEventArgs>();
            eventArgs[0].Message.ShouldBe("Testing");
            int c = 0;

            foreach (BuildEventArgs eventArg in eventArgs.Skip(1))
            {
                eventArg.ShouldBeOfType <BuildMessageEventArgs>();
                eventArg.Message.ShouldBe($"Testing {c++}");
            }
        }
コード例 #3
0
        // This is where the magic happens - returns one result per result target framework
        private AnalyzerResults BuildTargets(BuildEnvironment buildEnvironment, string targetFramework, string[] targetsToBuild, AnalyzerResults results)
        {
            using (CancellationTokenSource cancellation = new CancellationTokenSource())
            {
                using (AnonymousPipeLoggerServer pipeLogger = new AnonymousPipeLoggerServer(cancellation.Token))
                {
                    using (EventProcessor eventProcessor = new EventProcessor(Manager, this, BuildLoggers, pipeLogger, results != null))
                    {
                        // Run MSBuild
                        int    exitCode;
                        string fileName = GetCommand(buildEnvironment, targetFramework, targetsToBuild, pipeLogger.GetClientHandle(), out string arguments);
                        using (ProcessRunner processRunner = new ProcessRunner(fileName, arguments, Path.GetDirectoryName(ProjectFile.Path), GetEffectiveEnvironmentVariables(buildEnvironment), Manager.LoggerFactory))
                        {
                            processRunner.Exited = () => cancellation.Cancel();
                            processRunner.Start();
                            pipeLogger.ReadAll();
                            processRunner.Process.WaitForExit();
                            exitCode = processRunner.Process.ExitCode;
                        }

                        // Collect the results
                        results?.Add(eventProcessor.Results, exitCode == 0 && eventProcessor.OverallSuccess);
                    }
                }
            }
            return(results);
        }
コード例 #4
0
        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();
        }