/// <summary> /// Builds the specified target and returns the build result. /// </summary> /// <param name="project">The project to build</param> /// <param name="logger">The build logger to use. If null then a default logger will be used that dumps the build output to the console.</param> /// <param name="targets">Optional list of targets to execute</param> public static BuildResult BuildTargets(ProjectInstance projectInstance, ILogger logger, params string[] targets) { if (projectInstance == null) { throw new ArgumentNullException("projectInstance"); } if (logger == null) { throw new ArgumentNullException("logger"); } BuildParameters parameters = new BuildParameters(); parameters.Loggers = new ILogger[] { logger ?? new BuildLogger() }; parameters.UseSynchronousLogging = true; parameters.ShutdownInProcNodeOnBuildFinish = true; // required, other we can get an "Attempted to access an unloaded AppDomain" exception when the test finishes. BuildRequestData requestData = new BuildRequestData(projectInstance, targets); BuildResult result = null; BuildManager mgr = new BuildManager(); try { result = mgr.Build(parameters, requestData); result.ProjectStateAfterBuild = projectInstance; BuildUtilities.DumpProjectProperties(projectInstance, "Project properties post-build"); } finally { mgr.ShutdownAllNodes(); mgr.ResetCaches(); mgr.Dispose(); } return result; }
public void ShutdownNodesAfterParallelBuild() { ProjectCollection projectCollection = new ProjectCollection(); // Get number of MSBuild processes currently instantiated int numberProcsOriginally = (new List<Process>(Process.GetProcessesByName("MSBuild"))).Count; // Generate a theoretically unique directory to put our dummy projects in. string shutdownProjectDirectory = Path.Combine(Path.GetTempPath(), String.Format(CultureInfo.InvariantCulture, "VSNodeShutdown_{0}_UnitTest", Process.GetCurrentProcess().Id)); // Create the dummy projects we'll be "building" as our excuse to connect to and shut down // all the nodes. ProjectInstance rootProject = this.GenerateDummyProjects(shutdownProjectDirectory, numberProcsOriginally + 4, projectCollection); // Build the projects. BuildParameters buildParameters = new BuildParameters(projectCollection); buildParameters.OnlyLogCriticalEvents = true; buildParameters.MaxNodeCount = numberProcsOriginally + 4; buildParameters.EnableNodeReuse = true; buildParameters.DisableInProcNode = true; // Tell the build manager to not disturb process wide state buildParameters.SaveOperatingEnvironment = false; BuildRequestData requestData = new BuildRequestData(rootProject, new string[] { "Build" }, null); // Use a separate BuildManager for the node shutdown build, so that we don't have // to worry about taking dependencies on whether or not the existing ones have already // disappeared. BuildManager shutdownManager = new BuildManager("IdleNodeShutdown"); shutdownManager.Build(buildParameters, requestData); // Number of nodes after the build has to be greater than the original number int numberProcsAfterBuild = (new List<Process>(Process.GetProcessesByName("MSBuild"))).Count; Assert.IsTrue(numberProcsOriginally < numberProcsAfterBuild); // Shutdown all nodes shutdownManager.ShutdownAllNodes(); // Wait until all processes shut down Thread.Sleep(3000); // Number of nodes after the shutdown has to be smaller or equal the original number int numberProcsAfterShutdown = (new List<Process>(Process.GetProcessesByName("MSBuild"))).Count; Assert.IsTrue(numberProcsAfterShutdown <= numberProcsOriginally); // Delete directory with the dummy project if (Directory.Exists(shutdownProjectDirectory)) { Directory.Delete(shutdownProjectDirectory, true /* recursive delete */); } }