public void Execute(Project p) { // generate temporary filename string tempFileName; try { var protoFilename = Path.GetTempFileName(); // build more unique filename (include timestamp) tempFileName = string.Format("{0}{1}{2}", DateTime.Now.ToFileTime(), Path.GetFileName(protoFilename), ".cmd"); // prep filename with actual path tempFileName = Path.Combine(Path.GetDirectoryName(protoFilename), tempFileName); // move file to new .cmd File.Move(protoFilename, tempFileName); } catch (Exception e) { log.Error("Failed to generate temporary command script", e); throw BuilderException.CreateFailedToStartException(p, e); } TextWriter writer = null; if (p == null) { throw new BuilderException("No project provided", null); } try { if (ManagedBuilderSettings.IsDebug && ManagedBuilderSettings.DebugGenerateSingleFile) { writer = DebugCommandFile; Monitor.Enter(DebugCommandFile); } else { var fs = new FileStream(tempFileName, FileMode.Create, FileAccess.ReadWrite, FileShare.Read); writer = new StreamWriter(fs); } if (!ManagedBuilderSettings.CommandLineConfig.FrameworkCommands.ContainsKey(p.Framework)) { throw new BuilderException("Unsupported framework", p); } log.DebugFormat("{0}:Building command line script in [{1}]", p.Name, tempFileName); // setup property manager for this compilation instance var propMan = new PropertyManager(); var projectPath = p.Path; if (!Path.IsPathRooted(projectPath)) { projectPath = Path.Combine(PropertyManager.Common["build.directory"], projectPath); } log.DebugFormat("Project file: {0}", projectPath); log.DebugFormat("Project platform: {0}", p.PlatformName); log.DebugFormat("Project config: {0}", p.ConfigurationName); log.DebugFormat("Project build options: {0}", p.BuildOpt); log.DebugFormat("Project location: {0}", Path.GetDirectoryName(projectPath)); propMan.Add("project.file", projectPath); propMan.Add("project.buildopts", p.BuildOpt); propMan.Add("project.sccpath", p.SccPath); propMan.Add("project.platform", p.PlatformName); propMan.Add("project.configuration", p.ConfigurationName); propMan.AddDirectoryProperty("project.dir", Path.GetDirectoryName(projectPath)); var cmdlet = ManagedBuilderSettings.CommandLineConfig.FrameworkCommands[p.Framework]; var cmdletOut = string.Format("call {0} {1}", propMan.Evaluate(cmdlet.Commandlet), propMan.Evaluate(cmdlet.Arguments)); writer.WriteLine(cmdletOut); log.DebugFormat("{0}: {1}", p.Name, cmdletOut); // setup binplace if (ManagedBuilderSettings.CommandLineConfig.BinPlaceEnabled) { // location where binplace is stored var binPlaceLocation = propMan.Evaluate( ManagedBuilderSettings.CommandLineConfig.BinPlaceLocation); var binPlaceFile = propMan.Evaluate( ManagedBuilderSettings.CommandLineConfig.BinPlaceFilename); var binPlaceRoot = propMan.Evaluate( ManagedBuilderSettings.CommandLineConfig.BinPlaceRoot); foreach (var output in p.Outputs) { var actualDestPath = ""; if (!String.IsNullOrEmpty(output.DestPath)) { actualDestPath = string.Format( "-b {0} ", output.DestPath); } foreach (var path in output.PathList) { if (string.IsNullOrEmpty(path)) { log.Warn("Found an empty path in project outputs"); continue; } var binPlaceOut = string.Format( "{4} {0} -r {1} -p {2} {3}", actualDestPath, binPlaceRoot, // todo app.config needs to be set so that these values are evaluated Path.Combine(PropertyManager.Common["build.directory"], binPlaceFile), Path.Combine(PropertyManager.Common["build.directory"], path), binPlaceLocation ); // write output to batch script writer.WriteLine(binPlaceOut); log.DebugFormat("{0}: {1}", p.Name, binPlaceOut); } } } if (ManagedBuilderSettings.IsDebug && ManagedBuilderSettings.DebugGenerateSingleFile) { Monitor.Exit(DebugCommandFile); DebugCommandFile.Flush(); } else { writer.Close(); } log.DebugFormat("{0}: Executing command line script [{1}]", p.Name, tempFileName); var startInfo = new ProcessStartInfo(); startInfo.Arguments = string.Format("/c \"{0}\"", tempFileName); startInfo.FileName = "cmd.exe"; //startInfo.RedirectStandardOutput = true; startInfo.WindowStyle = ProcessWindowStyle.Hidden; startInfo.CreateNoWindow = true; startInfo.UseShellExecute = false; // todo: make it changeable via config startInfo.WorkingDirectory = PropertyManager.Common["build.directory"]; try { var process = Process.Start(startInfo); if (process == null) { throw BuilderException.CreateFailedToStartException(p); } using (process) { process.WaitForExit(); if (process.ExitCode != 0) { throw BuilderException.CreateBuildFailedDueToExitCodeException(p, process.ExitCode); } } } catch (BuilderException be) { throw; } catch (Exception e) { throw BuilderException.CreateFailedToStartException(p, e); } } finally { if (!ManagedBuilderSettings.IsDebug) { File.Delete(tempFileName); } } }
public static void LoadFromFile(string filename) { #region Config file loading and verification var doc = new XmlDocument(); try { doc.Load(File.OpenRead(filename)); } catch (Exception e) { throw ConfigurationException.AppConfigLoadFailure(e); } var xnList = doc.GetElementsByTagName("mbuilder"); if (xnList.Count != 1) { throw ConfigurationException.MultipleMBuilderSettings(); } #endregion var mbuildRoot = xnList[0] as XmlElement; if (mbuildRoot == null) { throw ConfigurationException.ConfigurationReadFailure(); } var nodeList = mbuildRoot.SelectSingleNode("setup/debug") as XmlElement; if (nodeList != null && nodeList.HasAttribute("enabled")) { IsDebug = nodeList.Attributes["enabled"].Value.ToLower() == bool.TrueString.ToLower(); } else { IsDebug = false; } var pm = new PropertyManager(); nodeList = mbuildRoot.SelectSingleNode("setup/asyncbuilders") as XmlElement; if (nodeList != null && nodeList.HasAttribute("count")) { var rawBuilderCount = nodeList.Attributes["count"].Value; var strBuildCount = pm.Evaluate(rawBuilderCount); var bldCount = 0; if (!Int32.TryParse(strBuildCount, out bldCount)) { throw ConfigurationException.ConfigurationReadFailure("setup/asyncbuilders"); } MaximumBuilders = bldCount; } else { MaximumBuilders = Environment.ProcessorCount; } Log.DebugFormat("Debug Mode: {0}", IsDebug); Log.DebugFormat("Asynchronous Builders: {0}", MaximumBuilders); nodeList = mbuildRoot.SelectSingleNode("builders/commandlinebuilder") as XmlElement; if (nodeList != null) { CommandLineConfig.Configure(nodeList); } }