internal static ProjectTargetInstance FactoryForDeserialization(ITranslator translator) { var instance = new ProjectTargetInstance(); var translatable = (ITranslatable)instance; translatable.Translate(translator); return(instance); }
private static void PrintTargetInfo(MBEX.ProjectTargetInstance target, int indentCount) { var indent = indentCount > 1 ? new StringBuilder().Insert(0, "| ", indentCount - 1).ToString() : ""; var tree = indentCount > 0 ? "| " : ""; var targetColor = indentCount > 0 ? (target.Name.StartsWith("_") ? ConsoleColor.DarkGreen : ConsoleColor.Green) : ConsoleColor.Cyan; Utils.WriteColor(indent + tree, ConsoleColor.White); Utils.WriteLineColor(target.Name, targetColor); }
public MSBuildTarget(ProjectTargetInstance pti, Project project, MSBuildFile parent = null) { this.Target = pti; this.Name = pti.Name; this.Inputs = pti.Inputs; this.Outputs = pti.Outputs; this.Location = pti.FullPath; this.DependsOnTargets = pti.DependsOnTargets; this.TargetColor = "Black"; this.FontStyle = "Normal"; if (!string.IsNullOrEmpty(this.Target.Condition)) { this.TargetCondition = this.Target.Condition; this.TargetColor = "Gray"; this.FontStyle = "Italic"; } if (project.Xml.DefaultTargets.Contains(pti.Name)) { this.TargetColor = "MediumBlue"; } if (project.Xml.InitialTargets.Contains(pti.Name)) { this.TargetColor = "LimeGreen"; } if (project.Xml.InitialTargets.Contains(pti.Name) && project.Xml.DefaultTargets.Contains(pti.Name)) { this.TargetColor = "Gold"; } this.Targets = new ObservableCollection<MSBuildTarget>(); string targets = project.ExpandString(pti.DependsOnTargets); targets = this.formatRegex.Replace(targets, string.Empty); int i = 0; foreach (var target in targets.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries)) { this.Targets.Add(new MSBuildTarget(target)); i++; } foreach (var x in project.Xml.Targets.Where(x => x.Name == pti.Name)) { this.BeforeTargets = x.BeforeTargets; this.AfterTargets = x.AfterTargets; } if (parent != null) { this.Parent = parent; } }
private ListViewItem CreateItem(ProjectTargetInstance target) { return new ListViewItem(new[] { target.Name, target.FullPath }) { Tag = target }; }
private void Trace(MBEX.ProjectTargetInstance target, int traceLevel = 0) { if (target == null) { return; } PrintTargetInfo(target, traceLevel); if (!string.IsNullOrWhiteSpace(target.DependsOnTargets)) { foreach (var dependency in target.Dependencies(project)) { Trace(dependency, traceLevel + 1); } } }
/// <summary> /// Gets a collection of ProjectTargetInstances that this target is dependent on in a given project. /// </summary> /// <param name="target"></param> /// <param name="project">The project to look in</param> /// <returns></returns> public static IEnumerable <MBEX.ProjectTargetInstance> Dependencies( this MBEX.ProjectTargetInstance target, MBEV.Project project) { var dependencies = new List <MBEX.ProjectTargetInstance>(); var dependencyTargetNames = project.ResolveAllProperties(target.DependsOnTargets) .Replace(Environment.NewLine, "") .Split(';'); foreach (var name in dependencyTargetNames) { if (!string.IsNullOrWhiteSpace(name)) { dependencies.Add(project.Targets[name.Trim()]); } } return(dependencies); }
/// <summary> /// Adds a task which builds the @(ProjectReference) items. /// </summary> private void AddReferencesBuildTask(ProjectInstance projectInstance, ProjectTargetInstance target, string targetToBuild, string outputItem) { ProjectTaskInstance task = target.AddTask("MSBuild", String.Empty, String.Empty); if (String.Equals(targetToBuild, "Clean", StringComparison.OrdinalIgnoreCase)) { task.SetParameter("Projects", "@(ProjectReference->Reverse())"); } else { task.SetParameter("Projects", "@(ProjectReference)"); // The references already have the tools versions and properties set on them. } if (targetToBuild != null) { task.SetParameter("Targets", targetToBuild); } task.SetParameter("BuildInParallel", "True"); task.SetParameter("Properties", SolutionProperties); // We only want to build "nonexistent" projects if we're building metaprojects, since they don't exist on disk. Otherwise, // we still want to error when the referenced project doesn't exist. task.SetParameter("SkipNonexistentProjects", "%(ProjectReference.SkipNonexistentProjects)"); if (outputItem != null) { task.AddOutputItem("TargetOutputs", outputItem, String.Empty); } }
/// <summary> /// Adds MSBuild tasks to a project target to pre-resolve its project references /// </summary> private void AddResolveProjectReferenceTasks ( ProjectInstance traversalProject, ProjectTargetInstance target, ProjectInSolution project, SolutionConfigurationInSolution solutionConfiguration, string outputReferenceItemName, string outputImportLibraryItemName, out string addedReferenceGuids ) { StringBuilder referenceGuids = new StringBuilder(); string message = null; // Suffix for the reference item name. Since we need to attach additional (different) metadata to every // reference item, we need to have helper item lists each with only one item int outputReferenceItemNameSuffix = 0; // Pre-resolve the MSBuild project references foreach (string projectReferenceGuid in project.ProjectReferences) { ProjectInSolution referencedProject = (ProjectInSolution)_solutionFile.ProjectsByGuid[projectReferenceGuid]; ProjectConfigurationInSolution referencedProjectConfiguration = null; if ((referencedProject != null) && (referencedProject.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out referencedProjectConfiguration)) && (referencedProjectConfiguration != null)) { string outputReferenceItemNameWithSuffix = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", outputReferenceItemName, outputReferenceItemNameSuffix); if ((referencedProject.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat) || ((referencedProject.ProjectType == SolutionProjectType.Unknown) && (referencedProject.CanBeMSBuildProjectFile(out message)))) { string condition = GetConditionStringForConfiguration(solutionConfiguration); if (traversalProject.EvaluateCondition(condition)) { bool specifyProjectToolsVersion = String.Equals(traversalProject.ToolsVersion, "2.0", StringComparison.OrdinalIgnoreCase) ? false : true; ProjectTaskInstance msbuildTask = AddMSBuildTaskInstance ( target, referencedProject.RelativePath, "GetTargetPath", referencedProjectConfiguration.ConfigurationName, referencedProjectConfiguration.PlatformName, specifyProjectToolsVersion ); msbuildTask.AddOutputItem("TargetOutputs", outputReferenceItemNameWithSuffix, null); } if (referenceGuids.Length > 0) { referenceGuids.Append(';'); } referenceGuids.Append(projectReferenceGuid); // This merges the one-item item list into the main list, adding the appropriate guid metadata ProjectTaskInstance createItemTask = target.AddTask("CreateItem", null, null); createItemTask.SetParameter("Include", "@(" + outputReferenceItemNameWithSuffix + ")"); createItemTask.SetParameter("AdditionalMetadata", "Guid=" + projectReferenceGuid); createItemTask.AddOutputItem("Include", outputReferenceItemName, null); } outputReferenceItemNameSuffix++; } } addedReferenceGuids = referenceGuids.ToString(); }
/// <summary> /// Helper method to add a call to the AspNetCompiler task into the given target. /// </summary> private void AddTaskForAspNetCompiler ( ProjectTargetInstance target, ProjectInSolution project, string conditionDescribingValidConfigurations ) { // Add a call to the AspNetCompiler task, conditioned on having a valid Configuration. ProjectTaskInstance newTask = target.AddTask("AspNetCompiler", conditionDescribingValidConfigurations, null); newTask.SetParameter("VirtualPath", "$(" + GenerateSafePropertyName(project, "AspNetVirtualPath") + ")"); newTask.SetParameter("PhysicalPath", "$(" + GenerateSafePropertyName(project, "AspNetPhysicalPath") + ")"); newTask.SetParameter("TargetPath", "$(" + GenerateSafePropertyName(project, "AspNetTargetPath") + ")"); newTask.SetParameter("Force", "$(" + GenerateSafePropertyName(project, "AspNetForce") + ")"); newTask.SetParameter("Updateable", "$(" + GenerateSafePropertyName(project, "AspNetUpdateable") + ")"); newTask.SetParameter("Debug", "$(" + GenerateSafePropertyName(project, "AspNetDebug") + ")"); newTask.SetParameter("KeyFile", "$(" + GenerateSafePropertyName(project, "AspNetKeyFile") + ")"); newTask.SetParameter("KeyContainer", "$(" + GenerateSafePropertyName(project, "AspNetKeyContainer") + ")"); newTask.SetParameter("DelaySign", "$(" + GenerateSafePropertyName(project, "AspNetDelaySign") + ")"); newTask.SetParameter("AllowPartiallyTrustedCallers", "$(" + GenerateSafePropertyName(project, "AspNetAPTCA") + ")"); newTask.SetParameter("FixedNames", "$(" + GenerateSafePropertyName(project, "AspNetFixedNames") + ")"); bool isDotNetFramework = false; // generate the target .NET Framework version based on the passed in TargetFrameworkMoniker. try { FrameworkName targetFramework = new FrameworkName(project.TargetFrameworkMoniker); if (String.Equals(targetFramework.Identifier, ".NETFramework", StringComparison.OrdinalIgnoreCase)) { isDotNetFramework = true; // As of .NET Framework 4.0, there are only two versions of aspnet_compiler.exe: 2.0 and 4.0. If // the TargetFrameworkVersion is less than 4.0, use the 2.0 version. Otherwise, just use the 4.0 // version of the executable, so that if say FV 4.1 is passed in, we don't throw an error. if (targetFramework.Version.Major >= 4) { newTask.SetParameter ( "ToolPath", FrameworkLocationHelper.GetPathToDotNetFramework(_version40) ); if (targetFramework.Version > _version40) { _loggingService.LogComment(_projectBuildEventContext, MessageImportance.Low, "AspNetCompiler.TargetingHigherFrameworksDefaultsTo40", project.ProjectName, targetFramework.Version.ToString()); } } else { string pathTo20 = FrameworkLocationHelper.GetPathToDotNetFramework(_version20); ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(pathTo20 != null, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(_solutionFile.FullPath), "AspNetCompiler.20NotInstalled"); newTask.SetParameter ( "ToolPath", pathTo20 ); } } } catch (Exception e) { if (ExceptionHandling.NotExpectedException(e)) { throw; } else { ProjectFileErrorUtilities.ThrowInvalidProjectFile ( new BuildEventFileInfo(_solutionFile.FullPath), e, "AspNetCompiler.InvalidTargetFrameworkMonikerFromException", project.ProjectName, project.TargetFrameworkMoniker, e.Message ); } } if (!isDotNetFramework) { ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile ( false, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(_solutionFile.FullPath), "AspNetCompiler.InvalidTargetFrameworkMonikerNotDotNET", project.ProjectName, project.TargetFrameworkMoniker ); } }
/// <summary> /// Adds an MSBuild task to a single metaproject. This is used in the traversal project. /// </summary> private void AddMetaprojectBuildTask(ProjectInstance traversalProject, ProjectInSolution project, ProjectTargetInstance target, string targetToBuild, string outputItem) { ProjectTaskInstance task = target.AddTask("MSBuild", OpportunisticIntern.InternStringIfPossible("'%(ProjectReference.Identity)' == '" + GetMetaprojectName(project) + "'"), String.Empty); task.SetParameter("Projects", "@(ProjectReference)"); if (targetToBuild != null) { task.SetParameter("Targets", targetToBuild); } task.SetParameter("BuildInParallel", "True"); task.SetParameter("ToolsVersion", MSBuildConstants.CurrentToolsVersion); task.SetParameter("Properties", SolutionProperties); task.SetParameter("SkipNonexistentProjects", "%(ProjectReference.SkipNonexistentProjects)"); if (outputItem != null) { task.AddOutputItem("TargetOutputs", outputItem, String.Empty); } }
/// <summary> /// Adds an MSBuild task to the specified target /// </summary> private static ProjectTaskInstance AddMSBuildTaskInstance ( ProjectTargetInstance target, string projectPath, string msbuildTargetName, string configurationName, string platformName, bool specifyProjectToolsVersion ) { ProjectTaskInstance msbuildTask = target.AddTask("MSBuild", null, null); msbuildTask.SetParameter("Projects", EscapingUtilities.Escape(projectPath)); if (msbuildTargetName != null && msbuildTargetName.Length > 0) { msbuildTask.SetParameter("Targets", msbuildTargetName); } string additionalProperties = string.Format( CultureInfo.InvariantCulture, "Configuration={0}; Platform={1}; BuildingSolutionFile=true; CurrentSolutionConfigurationContents=$(CurrentSolutionConfigurationContents); SolutionDir=$(SolutionDir); SolutionExt=$(SolutionExt); SolutionFileName=$(SolutionFileName); SolutionName=$(SolutionName); SolutionPath=$(SolutionPath)", EscapingUtilities.Escape(configurationName), EscapingUtilities.Escape(platformName) ); msbuildTask.SetParameter("Properties", additionalProperties); if (specifyProjectToolsVersion) { msbuildTask.SetParameter("ToolsVersion", "$(ProjectToolsVersion)"); } return msbuildTask; }
private void listView1_SelectedIndexChanged(object sender, EventArgs e) { this.SelectedTarget = (ProjectTargetInstance)listView1.SelectedItems[0].Tag; }
bool DoBuildTarget (ProjectTargetInstance target, TargetResult targetResult, InternalBuildArguments args) { var request = submission.BuildRequest; // Here we check cancellation (only after TargetStarted event). if (args.CheckCancel ()) { targetResult.Failure (new BuildAbortedException ("Build has canceled")); return false; } var propsToRestore = new Dictionary<string,string> (); var itemsToRemove = new List<ProjectItemInstance> (); try { // Evaluate additional target properties foreach (var c in target.Children.OfType<ProjectPropertyGroupTaskInstance> ()) { if (!args.Project.EvaluateCondition (c.Condition)) continue; foreach (var p in c.Properties) { if (!args.Project.EvaluateCondition (p.Condition)) continue; var value = args.Project.ExpandString (p.Value); propsToRestore.Add (p.Name, project.GetPropertyValue (value)); project.SetProperty (p.Name, value); } } // Evaluate additional target items foreach (var c in target.Children.OfType<ProjectItemGroupTaskInstance> ()) { if (!args.Project.EvaluateCondition (c.Condition)) continue; foreach (var item in c.Items) { if (!args.Project.EvaluateCondition (item.Condition)) continue; Func<string,ProjectItemInstance> creator = i => new ProjectItemInstance (project, item.ItemType, item.Metadata.Select (m => new KeyValuePair<string,string> (m.Name, m.Value)), i); foreach (var ti in project.GetAllItems (item.Include, item.Exclude, creator, creator, s => s == item.ItemType, (ti, s) => ti.SetMetadata ("RecurseDir", s))) itemsToRemove.Add (ti); } } foreach (var c in target.Children.OfType<ProjectOnErrorInstance> ()) { if (!args.Project.EvaluateCondition (c.Condition)) continue; throw new NotImplementedException (); } // run tasks foreach (var ti in target.Children.OfType<ProjectTaskInstance> ()) { current_task = ti; if (!args.Project.EvaluateCondition (ti.Condition)) { LogMessageEvent (new BuildMessageEventArgs (string.Format ("Task '{0}' was skipped because condition '{1}' wasn't met.", ti.Name, ti.Condition), null, null, MessageImportance.Low)); continue; } if (!RunBuildTask (target, ti, targetResult, args)) return false; } } finally { // restore temporary property state to the original state. foreach (var p in propsToRestore) { if (p.Value == string.Empty) project.RemoveProperty (p.Key); else project.SetProperty (p.Key, p.Value); } foreach (var item in itemsToRemove) project.RemoveItem (item); } return true; }
/// <summary> /// Marks this element as dirty. /// </summary> internal override void MarkDirty(string reason, string param) { base.MarkDirty(reason, param); TargetInstance = null; }
/// <summary> /// Add a call to the ResolveAssemblyReference task to crack the pre-resolved referenced /// assemblies for the complete list of dependencies, PDBs, satellites, etc. The invoke /// the Copy task to copy all these files (or at least the ones that RAR determined should /// be copied local) into the web project's bin directory. /// </summary> private static void AddTasksToCopyAllDependenciesIntoBinDir ( ProjectTargetInstance target, ProjectInSolution project, string referenceItemName, string conditionDescribingValidConfigurations ) { string copyLocalFilesItemName = referenceItemName + "_CopyLocalFiles"; string targetFrameworkDirectoriesName = GenerateSafePropertyName(project, "_TargetFrameworkDirectories"); string fullFrameworkRefAssyPathName = GenerateSafePropertyName(project, "_FullFrameworkReferenceAssemblyPaths"); string destinationFolder = String.Format(CultureInfo.InvariantCulture, @"$({0})\Bin\", GenerateSafePropertyName(project, "AspNetPhysicalPath")); // This is a bit of a hack. We're actually calling the "Copy" task on all of // the *non-existent* files. Why? Because we want to emit a warning in the // log for each non-existent file, and the Copy task does that nicely for us. // I would have used the <Warning> task except for the fact that we are in // string-resource lockdown. ProjectTaskInstance copyNonExistentReferencesTask = target.AddTask("Copy", String.Format(CultureInfo.InvariantCulture, "!Exists('%({0}.Identity)')", referenceItemName), "true"); copyNonExistentReferencesTask.SetParameter("SourceFiles", "@(" + referenceItemName + "->'%(FullPath)')"); copyNonExistentReferencesTask.SetParameter("DestinationFolder", destinationFolder); // We need to determine the appropriate TargetFrameworkMoniker to pass to GetReferenceAssemblyPaths, // so that we will pass the appropriate target framework directories to RAR. ProjectTaskInstance getRefAssembliesTask = target.AddTask("GetReferenceAssemblyPaths", null, null); getRefAssembliesTask.SetParameter("TargetFrameworkMoniker", project.TargetFrameworkMoniker); getRefAssembliesTask.SetParameter("RootPath", "$(TargetFrameworkRootPath)"); getRefAssembliesTask.AddOutputProperty("ReferenceAssemblyPaths", targetFrameworkDirectoriesName, null); getRefAssembliesTask.AddOutputProperty("FullFrameworkReferenceAssemblyPaths", fullFrameworkRefAssyPathName, null); // Call ResolveAssemblyReference on each of the .DLL files that were found on // disk from the .REFRESH files as well as the P2P references. RAR will crack // the dependencies, find PDBs, satellite assemblies, etc., and determine which // files need to be copy-localed. ProjectTaskInstance rarTask = target.AddTask("ResolveAssemblyReference", String.Format(CultureInfo.InvariantCulture, "Exists('%({0}.Identity)')", referenceItemName), null); rarTask.SetParameter("Assemblies", "@(" + referenceItemName + "->'%(FullPath)')"); rarTask.SetParameter("TargetFrameworkDirectories", "$(" + targetFrameworkDirectoriesName + ")"); rarTask.SetParameter("FullFrameworkFolders", "$(" + fullFrameworkRefAssyPathName + ")"); rarTask.SetParameter("SearchPaths", "{RawFileName};{TargetFrameworkDirectory};{GAC}"); rarTask.SetParameter("FindDependencies", "true"); rarTask.SetParameter("FindSatellites", "true"); rarTask.SetParameter("FindSerializationAssemblies", "true"); rarTask.SetParameter("FindRelatedFiles", "true"); rarTask.SetParameter("TargetFrameworkMoniker", project.TargetFrameworkMoniker); rarTask.AddOutputItem("CopyLocalFiles", copyLocalFilesItemName, null); // Copy all the copy-local files (reported by RAR) to the web project's "bin" // directory. ProjectTaskInstance copyTask = target.AddTask("Copy", conditionDescribingValidConfigurations, null); copyTask.SetParameter("SourceFiles", "@(" + copyLocalFilesItemName + ")"); copyTask.SetParameter ( "DestinationFiles", String.Format(CultureInfo.InvariantCulture, @"@({0}->'{1}%(DestinationSubDirectory)%(Filename)%(Extension)')", copyLocalFilesItemName, destinationFolder) ); }
/// <summary> /// This code handles the *.REFRESH files that are in the "bin" subdirectory of /// a web project. These .REFRESH files are just text files that contain absolute or /// relative paths to the referenced assemblies. The goal of these tasks is to /// search all *.REFRESH files and extract fully-qualified absolute paths for /// each of the references. /// </summary> private static void AddTasksToResolveAutoRefreshFileReferences ( ProjectTargetInstance target, ProjectInSolution project, string referenceItemName ) { string webRoot = "$(" + GenerateSafePropertyName(project, "AspNetPhysicalPath") + ")"; // Create an item list containing each of the .REFRESH files. ProjectTaskInstance createItemTask = target.AddTask("CreateItem", null, null); createItemTask.SetParameter("Include", webRoot + @"\Bin\*.refresh"); createItemTask.AddOutputItem("Include", referenceItemName + "_RefreshFile", null); // Read the lines out of each .REFRESH file; they should be paths to .DLLs. Put these paths // into an item list. ProjectTaskInstance readLinesTask = target.AddTask("ReadLinesFromFile", String.Format(CultureInfo.InvariantCulture, @" '%({0}_RefreshFile.Identity)' != '' ", referenceItemName), null); readLinesTask.SetParameter("File", String.Format(CultureInfo.InvariantCulture, @"%({0}_RefreshFile.Identity)", referenceItemName)); readLinesTask.AddOutputItem("Lines", referenceItemName + "_ReferenceRelPath", null); // Take those paths and combine them with the root of the web project to form either // an absolute path or a path relative to the .SLN file. These paths can be passed // directly to RAR later. ProjectTaskInstance combinePathTask = target.AddTask("CombinePath", null, null); combinePathTask.SetParameter("BasePath", webRoot); combinePathTask.SetParameter("Paths", String.Format(CultureInfo.InvariantCulture, @"@({0}_ReferenceRelPath)", referenceItemName)); combinePathTask.AddOutputItem("CombinedPaths", referenceItemName, null); }
// FIXME: Exception should be caught at caller site. bool DoBuildTarget (ProjectTargetInstance target, TargetResult targetResult, InternalBuildArguments args) { var request = submission.BuildRequest; // Here we check cancellation (only after TargetStarted event). if (args.CheckCancel ()) { targetResult.Failure (new BuildAbortedException ("Build has canceled")); return false; } try { foreach (var child in target.Children) { // Evaluate additional target properties var tp = child as ProjectPropertyGroupTaskInstance; if (tp != null) { if (!args.Project.EvaluateCondition (tp.Condition)) continue; foreach (var p in tp.Properties) { if (!args.Project.EvaluateCondition (p.Condition)) continue; var value = args.Project.ExpandString (p.Value); project.SetProperty (p.Name, value); } continue; } var ii = child as ProjectItemGroupTaskInstance; if (ii != null) { if (!args.Project.EvaluateCondition (ii.Condition)) continue; foreach (var item in ii.Items) { if (!args.Project.EvaluateCondition (item.Condition)) continue; project.AddItem (item.ItemType, project.ExpandString (item.Include)); } continue; } var task = child as ProjectTaskInstance; if (task != null) { current_task = task; if (!args.Project.EvaluateCondition (task.Condition)) { LogMessageEvent (new BuildMessageEventArgs (string.Format ("Task '{0}' was skipped because condition '{1}' wasn't met.", task.Name, task.Condition), null, null, MessageImportance.Low)); continue; } if (!RunBuildTask (target, task, targetResult, args)) return false; continue; } var onError = child as ProjectOnErrorInstance; if (onError != null) continue; // evaluated under catch clause. throw new NotSupportedException (string.Format ("Unexpected Target element children \"{0}\"", child.GetType ())); } } catch (Exception ex) { // fallback task specified by OnError element foreach (var c in target.Children.OfType<ProjectOnErrorInstance> ()) { if (!args.Project.EvaluateCondition (c.Condition)) continue; foreach (var fallbackTarget in project.ExpandString (c.ExecuteTargets).Split (';')) BuildTargetByName (fallbackTarget, args); } int line = target.Location != null ? target.Location.Line : 0; int col = target.Location != null ? target.Location.Column : 0; LogErrorEvent (new BuildErrorEventArgs (null, null, target.FullPath, line, col, 0, 0, ex.Message, null, null)); targetResult.Failure (ex); return false; } return true; }
/// <summary> /// Add a new error/warning/message tag into the given target /// </summary> private static ProjectTaskInstance AddErrorWarningMessageInstance ( ProjectTargetInstance target, string condition, string elementType, bool treatAsLiteral, string textResourceName, params object[] args ) { string code = null; string helpKeyword = null; string text = ResourceUtilities.FormatResourceString(out code, out helpKeyword, textResourceName, args); if (treatAsLiteral) { text = EscapingUtilities.Escape(text); } ProjectTaskInstance task = target.AddTask(elementType, condition, null); task.SetParameter("Text", text); if ((elementType != XMakeElements.message) && (code != null)) { task.SetParameter("Code", EscapingUtilities.Escape(code)); } if ((elementType != XMakeElements.message) && (helpKeyword != null)) { task.SetParameter("HelpKeyword", EscapingUtilities.Escape(helpKeyword)); } return task; }
bool RunBuildTask (ProjectTargetInstance target, ProjectTaskInstance taskInstance, TargetResult targetResult, InternalBuildArguments args) { var request = submission.BuildRequest; var host = request.HostServices == null ? null : request.HostServices.GetHostObject (request.ProjectFullPath, target.Name, taskInstance.Name); // Create Task instance. var factoryIdentityParameters = new Dictionary<string,string> (); #if NET_4_5 factoryIdentityParameters ["MSBuildRuntime"] = taskInstance.MSBuildRuntime; factoryIdentityParameters ["MSBuildArchitecture"] = taskInstance.MSBuildArchitecture; #endif var task = args.BuildTaskFactory.CreateTask (taskInstance.Name, factoryIdentityParameters, this); if (task == null) throw new InvalidOperationException (string.Format ("TaskFactory {0} returned null Task", args.BuildTaskFactory)); LogMessageEvent (new BuildMessageEventArgs (string.Format ("Using task {0} from {1}", taskInstance.Name, task.GetType ()), null, null, MessageImportance.Low)); task.HostObject = host; task.BuildEngine = this; // Prepare task parameters. var evaluator = new ExpressionEvaluator (project); var evaluatedTaskParams = taskInstance.Parameters.Select (p => new KeyValuePair<string,string> (p.Key, project.ExpandString (evaluator, p.Value))); var requiredProps = task.GetType ().GetProperties () .Where (p => p.CanWrite && p.GetCustomAttributes (typeof (RequiredAttribute), true).Any ()); var missings = requiredProps.Where (p => !evaluatedTaskParams.Any (tp => tp.Key.Equals (p.Name, StringComparison.OrdinalIgnoreCase))); if (missings.Any ()) throw new InvalidOperationException (string.Format ("Task {0} of type {1} is used without specifying mandatory property: {2}", taskInstance.Name, task.GetType (), string.Join (", ", missings.Select (p => p.Name).ToArray ()))); foreach (var p in evaluatedTaskParams) { switch (p.Key.ToLower ()) { case "condition": case "continueonerror": continue; } var prop = task.GetType ().GetProperty (p.Key); if (prop == null) throw new InvalidOperationException (string.Format ("Task {0} does not have property {1}", taskInstance.Name, p.Key)); if (!prop.CanWrite) throw new InvalidOperationException (string.Format ("Task {0} has property {1} but it is read-only.", taskInstance.Name, p.Key)); if (string.IsNullOrEmpty (p.Value) && !requiredProps.Contains (prop)) continue; try { prop.SetValue (task, ConvertTo (p.Value, prop.PropertyType, evaluator), null); } catch (Exception ex) { throw new InvalidOperationException (string.Format ("Failed to convert '{0}' for property '{1}' of type {2}", p.Value, prop.Name, prop.PropertyType), ex); } } // Do execute task. bool taskSuccess = false; event_source.FireTaskStarted (this, new TaskStartedEventArgs ("Task Started", null, project.FullPath, taskInstance.FullPath, taskInstance.Name)); try { taskSuccess = task.Execute (); if (!taskSuccess) { targetResult.Failure (null); if (!ContinueOnError) { return false; } } else { // Evaluate task output properties and items. foreach (var to in taskInstance.Outputs) { if (!project.EvaluateCondition (to.Condition)) continue; var toItem = to as ProjectTaskOutputItemInstance; var toProp = to as ProjectTaskOutputPropertyInstance; string taskParameter = toItem != null ? toItem.TaskParameter : toProp.TaskParameter; var pi = task.GetType ().GetProperty (taskParameter); if (pi == null) throw new InvalidOperationException (string.Format ("Task {0} does not have property {1} specified as TaskParameter", taskInstance.Name, toItem.TaskParameter)); if (!pi.CanRead) throw new InvalidOperationException (string.Format ("Task {0} has property {1} specified as TaskParameter, but it is write-only", taskInstance.Name, toItem.TaskParameter)); var value = pi.GetValue (task, null); var valueString = ConvertFrom (value); if (toItem != null) { LogMessageEvent (new BuildMessageEventArgs (string.Format ("Output Item {0} from TaskParameter {1}: {2}", toItem.ItemType, toItem.TaskParameter, valueString), null, null, MessageImportance.Low)); Action<ITaskItem> addItem = i => { var metadata = new ArrayList (i.MetadataNames).ToArray ().Cast<string> ().Select (n => new KeyValuePair<string,string> (n, i.GetMetadata (n))); args.Project.AddItem (toItem.ItemType, i.ItemSpec, metadata); }; var taskItemArray = value as ITaskItem []; if (taskItemArray != null) { foreach (var ti in taskItemArray) addItem (ti); } else { var taskItem = value as ITaskItem; if (taskItem != null) addItem (taskItem); else foreach (var item in valueString.Split (';')) args.Project.AddItem (toItem.ItemType, item); } } else { LogMessageEvent (new BuildMessageEventArgs (string.Format ("Output Property {0} from TaskParameter {1}: {2}", toProp.PropertyName, toProp.TaskParameter, valueString), null, null, MessageImportance.Low)); args.Project.SetProperty (toProp.PropertyName, valueString); } } } } finally { event_source.FireTaskFinished (this, new TaskFinishedEventArgs ("Task Finished", null, project.FullPath, taskInstance.FullPath, taskInstance.Name, taskSuccess)); } return true; }
private void ExecuteTarget(ProjectTargetInstance target) { IVsBuildManagerAccessor accessor = GetService(typeof(SVsBuildManagerAccessor)) as IVsBuildManagerAccessor; if (accessor.ClaimUIThreadForBuild() != VSConstants.S_OK) { throw new NotImplementedException(); } try { outputPane.Activate(); outputPane.Clear(); outputPane.OutputString(string.Format("------ Run target started: Project: {0}, Target: {1} ------" + Environment.NewLine, project.FullPath, target.Name)); var buildManager = BuildManager.DefaultBuildManager; buildManager.BeginBuild(new BuildParameters { Loggers = new[] { new IDEBuildLogger( outputPane, taskProvider, hierarchy) } }); BuildRequestData requestData = new BuildRequestData( project.CreateProjectInstance(), new[] { target.Name }, null, BuildRequestDataFlags.ReplaceExistingProjectInstance ); BuildManager.DefaultBuildManager .PendBuildRequest(requestData) .ExecuteAsync((submission) => { buildManager.EndBuild(); var targetResults = submission.BuildResult.ResultsByTarget.Values; outputPane.OutputString(string.Format("========== Build: {0} succeeded, {1} failed, {2} skipped ==========" + Environment.NewLine, targetResults.Count(tr => tr.ResultCode == TargetResultCode.Success), targetResults.Count(tr => tr.ResultCode == TargetResultCode.Failure), targetResults.Count(tr => tr.ResultCode == TargetResultCode.Skipped))); }, null); //BuildResult buildResult = submission.Execute(); //buildManager.EndBuild(); } finally { accessor.ReleaseUIThreadForBuild(); } }
/// <summary> /// Adds an MSBuild task to a real project. /// </summary> private void AddProjectBuildTask(ProjectInstance traversalProject, ProjectInSolution project, ProjectConfigurationInSolution projectConfiguration, ProjectTargetInstance target, string targetToBuild, string sourceItems, string condition, string outputItem) { ProjectTaskInstance task = target.AddTask("MSBuild", condition, String.Empty); task.SetParameter("Projects", sourceItems); if (targetToBuild != null) { task.SetParameter("Targets", targetToBuild); } task.SetParameter("BuildInParallel", "True"); task.SetParameter("ToolsVersion", GetToolsVersionAttributeForDirectMSBuildTask(traversalProject)); task.SetParameter("Properties", GetPropertiesAttributeForDirectMSBuildTask(projectConfiguration)); if (outputItem != null) { task.AddOutputItem("TargetOutputs", outputItem, String.Empty); } }