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++}"); } }
// 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)); } } }
// 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); }