using System.Collections; using System.IO; using System.Text; using Exortech.NetReflector; using ThoughtWorks.CruiseControl.Core.Util; namespace ThoughtWorks.CruiseControl.Core.Tasks { [ReflectorType("msdev")] public class MsDevTask : ITask { public const string VS6_REGISTRY_PATH = @"Software\Microsoft\VisualStudio\6.0"; public const string VS_REGISTRY_KEY = @"InstallDir"; public const string MSDEV_EXE = "msdev.com"; public const int DEFAULT_BUILD_TIMEOUT = 600; public const string DEFAULT_BUILDTYPE = "make"; public const string DEFAULT_PROJECT = ""; private IRegistry registry; private ProcessExecutor executor; private string executable; public MsDevTask() : this(new Registry(), new ProcessExecutor()) { } public MsDevTask(IRegistry registry, ProcessExecutor executor) { this.registry = registry; this.executor = executor; } [ReflectorProperty("executable", Required=false)] public string Executable { get { if (executable == null) { executable = ReadDevenvExecutableFromRegistry(); } return executable; } set { executable = value; } } private string ReadDevenvExecutableFromRegistry() { // Unfortunately the path in the registry is for the devenv directory... // we need the MsDev98 directory which seems to be reliably located at ..\..\ from // the path that's in the registry... string registryValue = registry.GetLocalMachineSubKeyValue(VS6_REGISTRY_PATH, VS_REGISTRY_KEY); return Path.Combine(Path.Combine(registryValue, @"..\..\MSDev98\Bin\"), MSDEV_EXE); } [ReflectorProperty("workspacefile")] public string WorkspaceFile; [ReflectorProperty("configuration")] public string Configuration; [ReflectorProperty("buildTimeoutSeconds", Required = false)] public int BuildTimeoutSeconds = DEFAULT_BUILD_TIMEOUT; [ReflectorProperty("buildtype", Required = false)] public string BuildType = DEFAULT_BUILDTYPE; [ReflectorProperty("project", Required = false)] public string Project = DEFAULT_PROJECT; public virtual void Run(IIntegrationResult result) { Util.ListenerFile.WriteInfo(result.ListenerFile, string.Format("Executing Msdev :{0}", Arguments)); ProcessResult processResult = AttemptToExecute(result, ProcessMonitor.GetProcessMonitorByProject(result.ProjectName)); result.AddTaskResult(new DevenvTaskResult(processResult)); Log.Info("Msdev build complete. Status: " + result.Status); if (processResult.TimedOut) { throw new BuilderException(this, string.Format("Msdev process timed out after {0} seconds.", BuildTimeoutSeconds)); } Util.ListenerFile.RemoveListenerFile(result.ListenerFile); } private ProcessResult AttemptToExecute(IIntegrationResult result, ProcessMonitor processMonitor) { string workingDirectory = result.WorkingDirectory; ProcessInfo processInfo = new ProcessInfo(Executable, Arguments, workingDirectory); processInfo.TimeOut = BuildTimeoutSeconds * 1000; IDictionary properties = result.IntegrationProperties; // Pass the integration environment variables to devenv. foreach (string key in properties.Keys) { if (properties[key] == null) processInfo.EnvironmentVariables[key] = null; else processInfo.EnvironmentVariables[key] = properties[key].ToString(); } Log.Info(string.Format("Starting build: {0} {1}", processInfo.FileName, processInfo.Arguments)); try { return executor.Execute(processInfo, processMonitor); } catch (IOException ex) { string message = string.Format("Unable to launch the msdev process. Please verify that you can invoke this command from the command line: {0} {1}", processInfo.FileName, processInfo.Arguments); throw new BuilderException(this, message, ex); } } private string Arguments { get { if (! StringUtil.IsBlank(Project)) { return string.Format("{0} /{1} {2} /project {3}", WorkspaceFile, BuildType, Configuration, Project); } else { return string.Format("{0} /{1} {2}", WorkspaceFile, BuildType, Configuration); } } } } }