private void ValidateProjectRelativePath(ProjectInSolution proj) { int num1 = proj.RelativePath.IndexOfAny(Path.GetInvalidPathChars()) == -1 ? 1 : 0; string errorSubCategoryResourceName1 = "SubCategoryForSolutionParsingErrors"; BuildEventFileInfo projectFile1 = new BuildEventFileInfo(this.SolutionFile, this.currentLineNumber, 0); string resourceName1 = "SolutionParseInvalidProjectFileNameCharacters"; object[] objArray1 = new object[2]; int index1 = 0; string projectName1 = proj.ProjectName; objArray1[index1] = (object)projectName1; int index2 = 1; string relativePath = proj.RelativePath; objArray1[index2] = (object)relativePath; int num2 = proj.RelativePath.Length > 0 ? 1 : 0; string errorSubCategoryResourceName2 = "SubCategoryForSolutionParsingErrors"; BuildEventFileInfo projectFile2 = new BuildEventFileInfo(this.SolutionFile, this.currentLineNumber, 0); string resourceName2 = "SolutionParseInvalidProjectFileNameEmpty"; object[] objArray2 = new object[1]; int index3 = 0; string projectName2 = proj.ProjectName; objArray2[index3] = (object)projectName2; }
internal void ParseNestedProjects() { while (true) { string input = this.ReadLine(); if (input != null && !(input == "EndGlobalSection")) { Match match = SolutionParser.crackPropertyLine.Match(input); string str1 = match.Groups["PROPERTYNAME"].Value.Trim(); string str2 = match.Groups["PROPERTYVALUE"].Value.Trim(); ProjectInSolution projectInSolution = (ProjectInSolution)this.projects[(object)str1]; int num = projectInSolution != null ? 1 : 0; string errorSubCategoryResourceName = "SubCategoryForSolutionParsingErrors"; BuildEventFileInfo projectFile = new BuildEventFileInfo(this.SolutionFile, this.currentLineNumber, 0); string resourceName = "SolutionParseNestedProjectUndefinedError"; object[] objArray = new object[2]; int index1 = 0; string str3 = str1; objArray[index1] = (object)str3; int index2 = 1; string str4 = str2; objArray[index2] = (object)str4; projectInSolution.ParentProjectGuid = str2; } else { break; } } }
//Constructor for MSBuild project public ProjectWrapper(ProjectInSolution project) { Name = project.ProjectName; Path = project.AbsolutePath; Items = new Lazy<IEnumerable<string>> (() => new Microsoft.Build.Evaluation.Project(project.AbsolutePath).Items.Select(x => x.EvaluatedInclude)); Id = new Guid(project.ProjectGuid); }
private void AddProjectToSolution(ProjectInSolution proj) { if (!string.IsNullOrEmpty(proj.ProjectGuid)) { this.projects[(object)proj.ProjectGuid] = (object)proj; } this.projectsInOrder.Add((object)proj); }
internal string GetProjectUniqueNameByGuid(string projectGuid) { ProjectInSolution projectInSolution = (ProjectInSolution)this.projects[(object)projectGuid]; if (projectInSolution != null) { return(projectInSolution.GetUniqueProjectName()); } return((string)null); }
internal string GetProjectRelativePathByGuid(string projectGuid) { ProjectInSolution projectInSolution = (ProjectInSolution)this.projects[(object)projectGuid]; if (projectInSolution != null) { return(projectInSolution.RelativePath); } return((string)null); }
private static string GetAbsoluteFilePath(ProjectInSolution project) { var path = project.AbsolutePath; if (string.IsNullOrEmpty(path)) { path = project.ProjectName; } return path; }
private static IDictionary<string, string> SpecializeArgsForSolutionProject(SolutionFile solution, ProjectInSolution p, IDictionary<string, string> args) { var targetPlatform = args.ContainsKey("Platform") ? args["Platform"] : solution.GetDefaultPlatformName(); var targetConfiguration = args.ContainsKey("Configuration") ? args["Configuration"] : solution.GetDefaultConfigurationName(); var targetSolutionConfiguration = solution.SolutionConfigurations.FirstOrDefault(conf => conf.ConfigurationName == targetConfiguration && conf.PlatformName == targetPlatform)?.FullName; var foo = targetSolutionConfiguration == null || !p.ProjectConfigurations.ContainsKey(targetSolutionConfiguration) ? null : p.ProjectConfigurations[targetSolutionConfiguration]; var copy = new Dictionary<string, string>(args); copy["Platform"] = foo == null ? targetPlatform : foo.PlatformName; copy["Configuration"] = foo == null ? targetConfiguration : foo.ConfigurationName; return copy; }
private async Task<SolutionItemTemplateInfo> CreateSolutionItemTemplateInfoAsync( SolutionFile solution, SolutionTemplateInfo solutionTemplateInfo, ProjectInSolution proj, IDictionary<Guid, SolutionFolderTemplateInfo> folders) { var id = Guid.Parse(proj.ProjectGuid); var parentId = proj.ParentProjectGuid == null ? Guid.Empty : Guid.Parse(proj.ParentProjectGuid); SolutionFolderTemplateInfo folder; if (!folders.TryGetValue(parentId, out folder)) { ProjectInSolution parentProj; if (solution.ProjectsByGuid.TryGetValue(proj.ParentProjectGuid, out parentProj)) { folder = (SolutionFolderTemplateInfo)await CreateSolutionItemTemplateInfoAsync(solution, solutionTemplateInfo, parentProj, folders); } } Debug.Assert(folder != null); SolutionItemTemplateInfo result; switch (proj.ProjectType) { case SolutionProjectType.KnownToBeMSBuildFormat: Project project = new Project(proj.AbsolutePath); var rootNamespace = project.Properties.Single(x => x.Name == "RootNamespace").EvaluatedValue; var targetName = project.Properties.Single(x => x.Name == "TargetName").EvaluatedValue; var rootName = AddRootName(rootNamespace, solutionTemplateInfo); result = new ProjectTemplateInfo(id, proj.ProjectName) { NameWithoutRoot = targetName.Substring(rootName.Length + 1), FileName = proj.AbsolutePath, ProjectConfigurations = GetProjectConfigurations(proj.ProjectConfigurations) }; break; case SolutionProjectType.SolutionFolder: if (folders.ContainsKey(id)) { return folders[id]; } result = new SolutionFolderTemplateInfo(id, proj.ProjectName); folders.Add(id, (SolutionFolderTemplateInfo)result); break; default: throw new ArgumentOutOfRangeException(); } folder.Items.Add(result); return result; }
internal void ParseFirstProjectLine(string firstLine, ProjectInSolution proj) { Match match = SolutionParser.crackProjectLine.Match(firstLine); string strA = match.Groups["PROJECTTYPEGUID"].Value.Trim(); proj.ProjectName = match.Groups["PROJECTNAME"].Value.Trim(); proj.RelativePath = match.Groups["RELATIVEPATH"].Value.Trim(); proj.ProjectGuid = match.Groups["PROJECTGUID"].Value.Trim(); this.ValidateProjectRelativePath(proj); if (string.Compare(strA, "{F184B08F-C81C-45F6-A57F-5ABD9991F28F}", StringComparison.OrdinalIgnoreCase) == 0 || string.Compare(strA, "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}", StringComparison.OrdinalIgnoreCase) == 0 || (string.Compare(strA, "{F2A71F9B-5D33-465A-A702-920D77279786}", StringComparison.OrdinalIgnoreCase) == 0 || string.Compare(strA, "{C8D11400-126E-41CD-887F-60BD40844F9E}", StringComparison.OrdinalIgnoreCase) == 0) || string.Compare(strA, "{E6FDF86B-F3D1-11D4-8576-0002A516ECE8}", StringComparison.OrdinalIgnoreCase) == 0) { proj.ProjectType = SolutionProjectType.KnownToBeMSBuildFormat; } else if (string.Compare(strA, "{2150E333-8FDC-42A3-9474-1A3956D46DE8}", StringComparison.OrdinalIgnoreCase) == 0) { proj.ProjectType = SolutionProjectType.SolutionFolder; } else if (string.Compare(strA, "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}", StringComparison.OrdinalIgnoreCase) == 0) { if (string.Equals(proj.Extension, ".vcxproj", StringComparison.OrdinalIgnoreCase)) { proj.ProjectType = SolutionProjectType.KnownToBeMSBuildFormat; } else { if (this.parsingForConversionOnly) { return; } BuildEventFileInfo projectFile = new BuildEventFileInfo(this.SolutionFile); string resourceName = "ProjectUpgradeNeededToVcxProj"; object[] objArray = new object[1]; int index = 0; string relativePath = proj.RelativePath; objArray[index] = (object)relativePath; } } else if (string.Compare(strA, "{E24C65DC-7377-472B-9ABA-BC803B73C61A}", StringComparison.OrdinalIgnoreCase) == 0) { proj.ProjectType = SolutionProjectType.WebProject; this.solutionContainsWebProjects = true; } else if (string.Compare(strA, "{2CFEAB61-6A3B-4EB8-B523-560B4BEEF521}", StringComparison.OrdinalIgnoreCase) == 0) { proj.ProjectType = SolutionProjectType.WebDeploymentProject; this.solutionContainsWebDeploymentProjects = true; } else { proj.ProjectType = SolutionProjectType.Unknown; } }
public void ParseFirstProjectLine_VC() { SolutionFile p = new SolutionFile(); p.FullPath = "c:\\foo.sln"; ProjectInSolution proj = new ProjectInSolution(p); p.ParseFirstProjectLine ( "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"Project name.vcproj\", \"Relative path\\to\\Project name.vcproj\", \"Unique name-GUID\"", proj ); Assert.Fail("Should not get here"); }
private static List<string> GetParentFolderChain(SolutionFile solutionFile, ProjectInSolution project) { var parentFolderChain = new List<string>(); var parentGuid = project.ParentProjectGuid; ProjectInSolution parentFolder; while (!string.IsNullOrEmpty(parentGuid) && solutionFile.ProjectsByGuid.TryGetValue(parentGuid, out parentFolder) && parentFolder != null) { parentFolderChain.Add(parentFolder.ProjectName); parentGuid = parentFolder.ParentProjectGuid; } parentFolderChain.Reverse(); return parentFolderChain; }
public void ParseFirstProjectLine_VC2() { SolutionFile p = new SolutionFile(); p.FullPath = "c:\\foo.sln"; ProjectInSolution proj = new ProjectInSolution(p); p.ParseFirstProjectLine ( "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"Project name.myvctype\", \"Relative path\\to\\Project name.myvctype\", \"Unique name-GUID\"", proj ); Assert.AreEqual(SolutionProjectType.KnownToBeMSBuildFormat, proj.ProjectType); Assert.AreEqual("Project name.myvctype", proj.ProjectName); Assert.AreEqual("Relative path\\to\\Project name.myvctype", proj.RelativePath); Assert.AreEqual("Unique name-GUID", proj.ProjectGuid); }
public void BasicParseFirstProjectLine() { SolutionFile p = new SolutionFile(); p.FullPath = "c:\\foo.sln"; ProjectInSolution proj = new ProjectInSolution(p); p.ParseFirstProjectLine ( "Project(\"{Project GUID}\") = \"Project name\", \"Relative path to project file\", \"Unique name-GUID\"", proj ); Assert.AreEqual(SolutionProjectType.Unknown, proj.ProjectType); Assert.AreEqual("Project name", proj.ProjectName); Assert.AreEqual("Relative path to project file", proj.RelativePath); Assert.AreEqual("Unique name-GUID", proj.ProjectGuid); }
internal string GetUniqueProjectName() { if (this.uniqueProjectName == null) { if (this.ProjectType == SolutionProjectType.WebProject || this.ProjectType == SolutionProjectType.EtpSubProject) { this.uniqueProjectName = ProjectInSolution.CleanseProjectName(this.ProjectName); } else { string str = string.Empty; if (this.ParentProjectGuid != null) { ProjectInSolution projectInSolution = (ProjectInSolution)this.ParentSolution.ProjectsByGuid[(object)this.ParentProjectGuid]; str = projectInSolution.GetUniqueProjectName() + "\\"; } this.uniqueProjectName = ProjectInSolution.CleanseProjectName(str + this.ProjectName); } } return(this.uniqueProjectName); }
/// <summary> /// Returns true if the specified project will build in the currently selected solution configuration. /// </summary> private static bool WouldProjectBuild(SolutionFile solutionFile, string selectedSolutionConfiguration, ProjectInSolution project, ProjectConfigurationInSolution projectConfiguration) { if (projectConfiguration == null) { if (project.ProjectType == SolutionProjectType.WebProject) { // Sometimes web projects won't have the configuration we need (Release typically.) But they should still build if there is // a solution configuration for it foreach (SolutionConfigurationInSolution configuration in solutionFile.SolutionConfigurations) { if (String.Equals(configuration.FullName, selectedSolutionConfiguration, StringComparison.OrdinalIgnoreCase)) { return true; } } } // No configuration, so it can't build. return false; } if (!projectConfiguration.IncludeInBuild) { // Not included in the build. return false; } return true; }
/// <summary> /// This method adds a new ProjectReference item to the specified instance. The reference will either be to its metaproject (if the project /// is a web project or has reference of its own) or to the project itself (if it has no references and is a normal MSBuildable project.) /// </summary> private void AddProjectReference(ProjectInstance traversalProject, ProjectInstance projectInstance, ProjectInSolution projectToAdd, ProjectConfigurationInSolution projectConfiguration, bool direct) { ProjectItemInstance item; if (direct) { // We can build this project directly, so add its reference. item = projectInstance.AddItem("ProjectReference", EscapingUtilities.Escape(projectToAdd.AbsolutePath), null); item.SetMetadata("ToolsVersion", GetToolsVersionMetadataForDirectMSBuildTask(traversalProject)); item.SetMetadata("SkipNonexistentProjects", "False"); // Skip if it doesn't exist on disk. item.SetMetadata("AdditionalProperties", GetPropertiesMetadataForProjectReference(traversalProject, GetConfigurationAndPlatformPropertiesString(projectConfiguration))); } else { // We cannot build directly, add the metaproject reference instead. item = projectInstance.AddItem("ProjectReference", GetMetaprojectName(projectToAdd), null); item.SetMetadata("ToolsVersion", traversalProject.ToolsVersion); item.SetMetadata("SkipNonexistentProjects", "Build"); // Instruct the MSBuild task to try to build even though the file doesn't exist on disk. item.SetMetadata("AdditionalProperties", GetPropertiesMetadataForProjectReference(traversalProject, SolutionConfigurationAndPlatformProperties)); } // Set raw config and platform for custom build steps to use if they wish // Configuration is null for web projects if (projectConfiguration != null) { item.SetMetadata("Configuration", projectConfiguration.ConfigurationName); item.SetMetadata("Platform", projectConfiguration.PlatformName); } }
/// <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> /// Takes a project in the solution and a base property name, and creates a new property name /// that can safely be used as an XML element name, and is also unique to that project (by /// embedding the project's GUID into the property name. /// </summary> private static string GenerateSafePropertyName ( ProjectInSolution proj, string propertyName ) { // XML element names cannot contain curly braces, so get rid of them from the project guid. string projectGuid = proj.ProjectGuid.Substring(1, proj.ProjectGuid.Length - 2); return "Project_" + projectGuid + "_" + propertyName; }
internal void ParseEtpProject(ProjectInSolution etpProj) { XmlDocument xmlDocument = new XmlDocument(); string filename = Path.Combine(this.solutionFileDirectory, etpProj.RelativePath); string directoryName = Path.GetDirectoryName(etpProj.RelativePath); try { xmlDocument.Load(filename); foreach (XmlNode xmlNode1 in xmlDocument.DocumentElement.SelectNodes("/EFPROJECT/GENERAL/References/Reference")) { string innerText = xmlNode1.SelectSingleNode("FILE").InnerText; if (innerText != null) { ProjectInSolution projectInSolution1 = new ProjectInSolution(this); projectInSolution1.RelativePath = Path.Combine(directoryName, innerText); this.ValidateProjectRelativePath(projectInSolution1); projectInSolution1.ProjectType = SolutionProjectType.EtpSubProject; ProjectInSolution projectInSolution2 = projectInSolution1; string relativePath = projectInSolution2.RelativePath; projectInSolution2.ProjectName = relativePath; XmlNode xmlNode2 = xmlNode1.SelectSingleNode("GUIDPROJECTID"); projectInSolution1.ProjectGuid = xmlNode2 == null ? string.Empty : xmlNode2.InnerText; this.AddProjectToSolution(projectInSolution1); if (this.IsEtpProjectFile(innerText)) { this.ParseEtpProject(projectInSolution1); } } } } catch (SecurityException ex) { string str1; // ISSUE: explicit reference operation // ISSUE: variable of a reference type string str2; // ISSUE: explicit reference operation // ISSUE: variable of a reference type string resourceName = "Shared.ProjectFileCouldNotBeLoaded"; object[] objArray = new object[2]; int index1 = 0; string relativePath = etpProj.RelativePath; objArray[index1] = (object)relativePath; int index2 = 1; string message = ex.Message; objArray[index2] = (object)message; } catch (NotSupportedException ex) { string str1; // ISSUE: explicit reference operation // ISSUE: variable of a reference type string str2; // ISSUE: explicit reference operation // ISSUE: variable of a reference type string resourceName = "Shared.ProjectFileCouldNotBeLoaded"; object[] objArray = new object[2]; int index1 = 0; string relativePath = etpProj.RelativePath; objArray[index1] = (object)relativePath; int index2 = 1; string message = ex.Message; objArray[index2] = (object)message; } }
public void ParseFirstProjectLine_InvalidProject() { SolutionFile p = new SolutionFile(); p.FullPath = "c:\\foo.sln"; ProjectInSolution proj = new ProjectInSolution(p); p.ParseFirstProjectLine ( "Project(\"{Project GUID}\") = \"\", \"src\\.proj\", \"Unique name-GUID\"", proj ); Assert.AreEqual(SolutionProjectType.Unknown, proj.ProjectType); Assert.IsTrue(proj.ProjectName.StartsWith("EmptyProjectName")); Assert.AreEqual("src\\.proj", proj.RelativePath); Assert.AreEqual("Unique name-GUID", proj.ProjectGuid); }
/// <summary> /// Adds a target for a project whose type is unknown and we cannot build. We will emit an error or warning as appropriate. /// </summary> private void AddMetaprojectTargetForUnknownProjectType(ProjectInstance traversalProject, ProjectInstance metaprojectInstance, ProjectInSolution project, string targetName, string unknownProjectTypeErrorMessage) { ProjectTargetInstance newTarget = metaprojectInstance.AddTarget(targetName ?? "Build", "'$(CurrentSolutionConfigurationContents)' != ''", null, null, null, null, null, false /* legacy target returns behaviour */); foreach (SolutionConfigurationInSolution solutionConfiguration in _solutionFile.SolutionConfigurations) { ProjectConfigurationInSolution projectConfiguration = null; ProjectTaskInstance newTask = null; if (project.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out projectConfiguration)) { if (projectConfiguration.IncludeInBuild) { // Only add the task if it would run in this configuration. if (!traversalProject.EvaluateCondition(GetConditionStringForConfiguration(solutionConfiguration))) { continue; } if (unknownProjectTypeErrorMessage == null) { // we haven't encountered any problems accessing the project file in the past, but do not support // building this project type newTask = AddErrorWarningMessageInstance ( newTarget, null, XMakeElements.warning, true, "SolutionParseUnknownProjectType", project.RelativePath ); } else { // this project file may be of supported type, but we have encountered problems accessing it newTask = AddErrorWarningMessageInstance ( newTarget, null, XMakeElements.warning, true, "SolutionParseErrorReadingProject", project.RelativePath, unknownProjectTypeErrorMessage ); } } else { newTask = AddErrorWarningMessageInstance ( newTarget, null, XMakeElements.message, true, "SolutionProjectSkippedForBuilding", project.ProjectName, solutionConfiguration.FullName ); } } else { newTask = AddErrorWarningMessageInstance ( newTarget, null, XMakeElements.warning, true, "SolutionProjectConfigurationMissing", project.ProjectName, solutionConfiguration.FullName ); } } }
/// <summary> /// Produces a set of targets which allows the MSBuild scheduler to schedule projects in the order automatically by /// following their dependencies without enforcing build levels. /// </summary> /// <remarks> /// We want MSBuild to be able to parallelize the builds of these projects where possible and still honor references. /// Since the project files referenced by the solution do not (necessarily) themselves contain actual project references /// to the projects they depend on, we need to synthesize this relationship ourselves. This is done by creating a target /// which first invokes the project's dependencies, then invokes the actual project itself. However, invoking the /// dependencies must also invoke their dependencies and so on down the line. /// /// Additionally, we do not wish to create a separate MSBuild project to contain this target yet we want to parallelize /// calls to these targets. The way to do this is to pass in different global properties to the same project in the same /// MSBuild call. MSBuild easily allows this using the AdditionalProperties metadata which can be specified on an Item. /// /// Assuming the solution project we are generating is called "foo.proj", we can accomplish this parallelism as follows: /// <ItemGroup> /// <ProjectReference Include="Project0"/> /// <ProjectReference Include="Project1"/> /// <ProjectReference Include="Project2"/> /// </ItemGroup> /// /// We now have expressed the top level reference to all projects as @(SolutionReference) and each project's /// set of references as @(PROJECTNAMEReference). We construct our target as: /// /// <Target Name="Build"> /// <MSBuild Projects="@(ProjectReference)" Targets="Build" /> /// <MSBuild Projects="actualProjectName" Targets="Build" /> /// </Target> /// /// The first MSBuild call re-invokes the solution project instructing it to build the reference projects for the /// current project. The second MSBuild call invokes the actual project itself. Because all reference projects have /// the same additional properties, MSBuild will only build the first one it comes across and the rest will be /// satisfied from the cache. /// </remarks> private ProjectInstance CreateMetaproject(ProjectInstance traversalProject, ProjectInSolution project, ProjectConfigurationInSolution projectConfiguration) { // Create a new project instance with global properties and tools version from the existing project ProjectInstance metaprojectInstance = new ProjectInstance(EscapingUtilities.UnescapeAll(GetMetaprojectName(project)), traversalProject, GetMetaprojectGlobalProperties(traversalProject)); // Add the project references which must build before this one. AddMetaprojectReferenceItems(traversalProject, metaprojectInstance, project); // This string holds the error message generated when we try to determine if a project is an MSBuild format // project but it is not. string unknownProjectTypeErrorMessage; if (project.ProjectType == SolutionProjectType.WebProject) { AddMetaprojectTargetForWebProject(traversalProject, metaprojectInstance, project, null); AddMetaprojectTargetForWebProject(traversalProject, metaprojectInstance, project, "Clean"); AddMetaprojectTargetForWebProject(traversalProject, metaprojectInstance, project, "Rebuild"); AddMetaprojectTargetForWebProject(traversalProject, metaprojectInstance, project, "Publish"); } else if ((project.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat) || (project.CanBeMSBuildProjectFile(out unknownProjectTypeErrorMessage))) { string safeItemNameFromProjectName = MakeIntoSafeItemName(project.ProjectName); string targetOutputItemName = string.Format(CultureInfo.InvariantCulture, "{0}BuildOutput", safeItemNameFromProjectName); AddMetaprojectTargetForManagedProject(traversalProject, metaprojectInstance, project, projectConfiguration, "Clean", null); AddMetaprojectTargetForManagedProject(traversalProject, metaprojectInstance, project, projectConfiguration, null, targetOutputItemName); AddMetaprojectTargetForManagedProject(traversalProject, metaprojectInstance, project, projectConfiguration, "Rebuild", targetOutputItemName); AddMetaprojectTargetForManagedProject(traversalProject, metaprojectInstance, project, projectConfiguration, "Publish", null); } else { AddMetaprojectTargetForUnknownProjectType(traversalProject, metaprojectInstance, project, null, unknownProjectTypeErrorMessage); AddMetaprojectTargetForUnknownProjectType(traversalProject, metaprojectInstance, project, "Clean", unknownProjectTypeErrorMessage); AddMetaprojectTargetForUnknownProjectType(traversalProject, metaprojectInstance, project, "Rebuild", unknownProjectTypeErrorMessage); AddMetaprojectTargetForUnknownProjectType(traversalProject, metaprojectInstance, project, "Publish", unknownProjectTypeErrorMessage); } return metaprojectInstance; }
/// <summary> /// Adds the targets which build the dependencies and actual project for a metaproject. /// </summary> private void AddMetaprojectTargetForManagedProject(ProjectInstance traversalProject, ProjectInstance metaprojectInstance, ProjectInSolution project, ProjectConfigurationInSolution projectConfiguration, string targetName, string outputItem) { string outputItemAsItem = null; if (!String.IsNullOrEmpty(outputItem)) { outputItemAsItem = "@(" + outputItem + ")"; } ProjectTargetInstance target = metaprojectInstance.AddTarget(targetName ?? "Build", String.Empty, String.Empty, outputItemAsItem, null, String.Empty, String.Empty, false /* legacy target returns behaviour */); AddReferencesBuildTask(metaprojectInstance, target, targetName, outputItem); // Add the task to build the actual project. AddProjectBuildTask(traversalProject, project, projectConfiguration, target, targetName, EscapingUtilities.Escape(project.AbsolutePath), String.Empty, outputItem); }
/// <summary> /// Adds a set of items which describe the references for this project. /// </summary> private void AddMetaprojectReferenceItems(ProjectInstance traversalProject, ProjectInstance metaprojectInstance, ProjectInSolution project) { foreach (string dependencyProjectGuid in project.Dependencies) { ProjectInSolution dependencyProject; if (!_solutionFile.ProjectsByGuid.TryGetValue(dependencyProjectGuid, out dependencyProject)) { ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile ( false, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(traversalProject.FullPath), "SolutionParseProjectDepNotFoundError", project.ProjectGuid, dependencyProjectGuid ); } else { ProjectConfigurationInSolution dependencyProjectConfiguration = null; if (dependencyProject.ProjectConfigurations.TryGetValue(_selectedSolutionConfiguration, out dependencyProjectConfiguration) && WouldProjectBuild(_solutionFile, _selectedSolutionConfiguration, dependencyProject, dependencyProjectConfiguration)) { bool canBuildDirectly = CanBuildDirectly(traversalProject, dependencyProject, dependencyProjectConfiguration); AddProjectReference(traversalProject, metaprojectInstance, dependencyProject, dependencyProjectConfiguration, canBuildDirectly); } } } }
/// <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> /// Add a target for a Venus project into the XML doc that's being generated. This /// target will call the AspNetCompiler task. /// </summary> private void AddMetaprojectTargetForWebProject(ProjectInstance traversalProject, ProjectInstance metaprojectInstance, ProjectInSolution project, string targetName) { // Add a supporting target called "GetFrameworkPathAndRedistList". AddTargetForGetFrameworkPathAndRedistList(metaprojectInstance); ProjectTargetInstance newTarget = metaprojectInstance.AddTarget(targetName ?? "Build", ComputeTargetConditionForWebProject(project), null, null, null, null, "GetFrameworkPathAndRedistList", false /* legacy target returns behaviour */); // Build the references AddReferencesBuildTask(metaprojectInstance, newTarget, targetName, null); if (targetName == "Clean") { // Well, hmmm. The AspNetCompiler task doesn't support any kind of // a "Clean" operation. The best we can really do is offer up a // message saying so. AddErrorWarningMessageInstance(newTarget, null, XMakeElements.message, true, "SolutionVenusProjectNoClean"); } else if (targetName == "Publish") { // Well, hmmm. The AspNetCompiler task doesn't support any kind of // a "Publish" operation. The best we can really do is offer up a // message saying so. AddErrorWarningMessageInstance(newTarget, null, XMakeElements.message, true, "SolutionVenusProjectNoPublish"); } else { // For normal build and "Rebuild", just call the AspNetCompiler task with the // correct parameters. But before calling the AspNetCompiler task, we need to // do a bunch of prep work regarding references. // We're going to build up an MSBuild condition string that represents the valid Configurations. // We do this by OR'ing together individual conditions, each of which compares $(Configuration) // with a valid configuration name. We init our condition string to "false", so we can easily // OR together more stuff as we go, and also easily take the negation of the condition by putting // a ! around the whole thing. StringBuilder conditionDescribingValidConfigurations = new StringBuilder("(false)"); // Loop through all the valid configurations and add a PropertyGroup for each one. foreach (DictionaryEntry aspNetConfiguration in project.AspNetConfigurations) { string configurationName = (string)aspNetConfiguration.Key; AspNetCompilerParameters aspNetCompilerParameters = (AspNetCompilerParameters)aspNetConfiguration.Value; // We only add the PropertyGroup once per Venus project. Without the following "if", we would add // the same identical PropertyGroup twice, once when AddTargetForWebProject is called with // subTargetName=null and once when subTargetName="Rebuild". if (targetName == null) { AddPropertyGroupForAspNetConfiguration(traversalProject, metaprojectInstance, project, configurationName, aspNetCompilerParameters, _solutionFile.FullPath); } // Update our big condition string to include this configuration. conditionDescribingValidConfigurations.Append(" or "); conditionDescribingValidConfigurations.Append(String.Format(CultureInfo.InvariantCulture, "('$(AspNetConfiguration)' == '{0}')", EscapingUtilities.Escape(configurationName))); } StringBuilder referenceItemName = new StringBuilder(GenerateSafePropertyName(project, "References")); if (!string.IsNullOrEmpty(targetName)) { referenceItemName.Append('_'); referenceItemName.Append(targetName); } // Add tasks to resolve project references of this web project, if any if (project.ProjectReferences.Count > 0) { // This is a bit tricky. Even though web projects don't use solution configurations, // we want to use the current solution configuration to build the proper configurations // of referenced projects. foreach (SolutionConfigurationInSolution solutionConfiguration in _solutionFile.SolutionConfigurations) { string referenceProjectGuids = null; AddResolveProjectReferenceTasks ( traversalProject, newTarget, project, solutionConfiguration, referenceItemName.ToString(), null /* don't care about native references */, out referenceProjectGuids ); } } // Add tasks to capture the auto-refreshed file references (those .REFRESH files). AddTasksToResolveAutoRefreshFileReferences(newTarget, project, referenceItemName.ToString()); // Add a call to RAR (ResolveAssemblyReference) and the Copy task to put the referenced // project outputs in the right place AddTasksToCopyAllDependenciesIntoBinDir(newTarget, project, referenceItemName.ToString(), conditionDescribingValidConfigurations.ToString()); // Add a call to the AspNetCompiler task, conditioned on having a valid Configuration. AddTaskForAspNetCompiler(newTarget, project, conditionDescribingValidConfigurations.ToString()); // Add a call to the <Message> task, conditioned on having an *invalid* Configuration. The // message says that we're skipping the Venus project because it's either not enabled // for precompilation, or doesn't support the given configuration. ProjectTaskInstance skippingVenusProjectMessageTask = AddErrorWarningMessageInstance ( newTarget, "!(" + conditionDescribingValidConfigurations.ToString() + ")", XMakeElements.message, false, "SolutionVenusProjectSkipped" ); } }
/// <summary> /// Returns true if the specified project can be built directly, without using a metaproject. /// </summary> private bool CanBuildDirectly(ProjectInstance traversalProject, ProjectInSolution projectToAdd, ProjectConfigurationInSolution projectConfiguration) { // Can we build this project directly, without a metaproject? We can if it's MSBuild-able and has no references building in this configuration. bool canBuildDirectly = false; string unknownProjectTypeErrorMessage; if ((projectToAdd.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat) || (projectToAdd.CanBeMSBuildProjectFile(out unknownProjectTypeErrorMessage))) { canBuildDirectly = true; foreach (string dependencyProjectGuid in projectToAdd.Dependencies) { ProjectInSolution dependencyProject; if (!_solutionFile.ProjectsByGuid.TryGetValue(dependencyProjectGuid, out dependencyProject)) { ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile ( false, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(traversalProject.FullPath), "SolutionParseProjectDepNotFoundError", projectToAdd.ProjectGuid, dependencyProjectGuid ); } if (WouldProjectBuild(_solutionFile, _selectedSolutionConfiguration, dependencyProject, projectConfiguration)) { // This is a reference we would have to build, so we can't build the project directly. canBuildDirectly = false; break; } } } return canBuildDirectly; }
/// <summary> /// Adds a traversal target which invokes a specified target on a single project. This creates targets called "Project", "Project:Rebuild", "Project:Clean", "Project:Publish" etc. /// </summary> private void AddTraversalTargetForProject(ProjectInstance traversalProject, ProjectInSolution project, ProjectConfigurationInSolution projectConfiguration, string targetToBuild, string outputItem, bool canBuildDirectly) { string baseProjectName = ProjectInSolution.DisambiguateProjectTargetName(project.GetUniqueProjectName()); string actualTargetName = baseProjectName; if (targetToBuild != null) { actualTargetName += ":" + targetToBuild; } // The output item name is the concatenation of the project name with the specified outputItem. In the typical case, if the // project name is MyProject, the outputItemName will be MyProjectBuildOutput, and the outputItemAsItem will be @(MyProjectBuildOutput). // In the case where the project contains characters not allowed as Xml element attribute values, those characters will // be replaced with underscores. In the case where MyProject is actually unrepresentable in Xml, then the // outputItemName would be _________BuildOutput. string outputItemName = null; string outputItemAsItem = null; if (!String.IsNullOrEmpty(outputItem)) { outputItemName = MakeIntoSafeItemName(baseProjectName) + outputItem; outputItemAsItem = "@(" + outputItemName + ")"; } ProjectTargetInstance targetElement = traversalProject.AddTarget(actualTargetName, null, null, outputItemAsItem, null, null, null, false /* legacy target returns behaviour */); if (canBuildDirectly) { AddProjectBuildTask(traversalProject, project, projectConfiguration, targetElement, targetToBuild, "@(ProjectReference)", "'%(ProjectReference.Identity)' == '" + EscapingUtilities.Escape(project.AbsolutePath) + "'", outputItemName); } else { AddMetaprojectBuildTask(traversalProject, project, targetElement, targetToBuild, outputItemName); } }
/// <summary> /// Returns the metaproject name for a given project. /// </summary> private string GetMetaprojectName(ProjectInSolution project) { string baseName; if (project.ProjectType == SolutionProjectType.WebProject) { baseName = Path.Combine(_solutionFile.SolutionFileDirectory, MakeIntoSafeItemName(project.GetUniqueProjectName())); } else { baseName = project.AbsolutePath; } if (String.IsNullOrEmpty(baseName)) { baseName = project.ProjectName; } baseName = FileUtilities.EnsureNoTrailingSlash(baseName); return SolutionProjectGenerator.GetMetaprojectName(baseName); }
/// <summary> /// Adds a dependency to the project based on the specified guid string. /// </summary> /// <remarks> /// If the string is null or empty, no dependency is added and this is not considered an error. /// </remarks> private void AddDependencyByGuid(ProjectInSolution project, string dependencyGuid) { if (!String.IsNullOrEmpty(dependencyGuid)) { if (_solutionFile.ProjectsByGuid.ContainsKey(dependencyGuid)) { project.AddDependency(dependencyGuid); } else { _loggingService.LogWarning ( _projectBuildEventContext, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(_solutionFile.FullPath), "SolutionParseProjectDepNotFoundError", project.ProjectGuid, dependencyGuid ); } } }
private void ParseProject(string firstLine) { ProjectInSolution projectInSolution = new ProjectInSolution(this); this.ParseFirstProjectLine(firstLine, projectInSolution); label_10: string str1; while ((str1 = this.ReadLine()) != null && !(str1 == "EndProject")) { if (str1.StartsWith("ProjectSection(ProjectDependencies)", StringComparison.Ordinal)) { string input = this.ReadLine(); while (true) { if (input != null && !input.StartsWith("EndProjectSection", StringComparison.Ordinal)) { Match match = SolutionParser.crackPropertyLine.Match(input); int num = match.Success ? 1 : 0; string errorSubCategoryResourceName = "SubCategoryForSolutionParsingErrors"; BuildEventFileInfo projectFile = new BuildEventFileInfo(this.SolutionFile, this.currentLineNumber, 0); string resourceName = "SolutionParseProjectDepGuidError"; object[] objArray = new object[1]; int index = 0; string projectName = projectInSolution.ProjectName; objArray[index] = (object)projectName; string str2 = match.Groups["PROPERTYNAME"].Value.Trim(); projectInSolution.Dependencies.Add((object)str2); input = this.ReadLine(); } else { goto label_10; } } } else if (str1.StartsWith("ProjectSection(WebsiteProperties)", StringComparison.Ordinal)) { string input = this.ReadLine(); while (true) { if (input != null && !input.StartsWith("EndProjectSection", StringComparison.Ordinal)) { Match match = SolutionParser.crackPropertyLine.Match(input); int num = match.Success ? 1 : 0; string errorSubCategoryResourceName = "SubCategoryForSolutionParsingErrors"; BuildEventFileInfo projectFile = new BuildEventFileInfo(this.SolutionFile, this.currentLineNumber, 0); string resourceName = "SolutionParseWebProjectPropertiesError"; object[] objArray = new object[1]; int index = 0; string projectName = projectInSolution.ProjectName; objArray[index] = (object)projectName; string propertyName = match.Groups["PROPERTYNAME"].Value.Trim(); string propertyValue = match.Groups["PROPERTYVALUE"].Value.Trim(); this.ParseAspNetCompilerProperty(projectInSolution, propertyName, propertyValue); input = this.ReadLine(); } else { goto label_10; } } } } int num1 = str1 != null ? 1 : 0; string errorSubCategoryResourceName1 = "SubCategoryForSolutionParsingErrors"; BuildEventFileInfo projectFile1 = new BuildEventFileInfo(this.SolutionFile); string resourceName1 = "SolutionParseProjectEofError"; object[] objArray1 = new object[1]; int index1 = 0; string projectName1 = projectInSolution.ProjectName; objArray1[index1] = (object)projectName1; if (projectInSolution == null) { return; } this.AddProjectToSolution(projectInSolution); if (!this.IsEtpProjectFile(projectInSolution.RelativePath)) { return; } this.ParseEtpProject(projectInSolution); }
/// <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) ); }
public void ParseFirstProjectLineWhereProjectNameHasSpecialCharacters() { SolutionFile p = new SolutionFile(); p.FullPath = "c:\\foo.sln"; ProjectInSolution proj = new ProjectInSolution(p); p.ParseFirstProjectLine ( "Project(\"{Project GUID}\") = \"MyProject,(=IsGreat)\", \"Relative path to project file\" , \"Unique name-GUID\"", proj ); Assert.AreEqual(SolutionProjectType.Unknown, proj.ProjectType); Assert.AreEqual("MyProject,(=IsGreat)", proj.ProjectName); Assert.AreEqual("Relative path to project file", proj.RelativePath); Assert.AreEqual("Unique name-GUID", proj.ProjectGuid); }
/// <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); }
private void ParseAspNetCompilerProperty(ProjectInSolution proj, string propertyName, string propertyValue) { int length = propertyName.IndexOf('.'); if (length != -1) { string str1 = propertyName.Substring(0, length); string str2 = propertyName.Length - length > 0 ? propertyName.Substring(length + 1, propertyName.Length - length - 1) : ""; propertyValue = this.TrimQuotes(propertyValue); object obj = proj.AspNetConfigurations[(object)str1]; AspNetCompilerParameters compilerParameters; if (obj == null) { compilerParameters = new AspNetCompilerParameters(); compilerParameters.aspNetVirtualPath = string.Empty; compilerParameters.aspNetPhysicalPath = string.Empty; compilerParameters.aspNetTargetPath = string.Empty; compilerParameters.aspNetForce = string.Empty; compilerParameters.aspNetUpdateable = string.Empty; compilerParameters.aspNetDebug = string.Empty; compilerParameters.aspNetKeyFile = string.Empty; compilerParameters.aspNetKeyContainer = string.Empty; compilerParameters.aspNetDelaySign = string.Empty; compilerParameters.aspNetAPTCA = string.Empty; compilerParameters.aspNetFixedNames = string.Empty; } else { compilerParameters = (AspNetCompilerParameters)obj; } if (str2 == "AspNetCompiler.VirtualPath") { compilerParameters.aspNetVirtualPath = propertyValue; } else if (str2 == "AspNetCompiler.PhysicalPath") { compilerParameters.aspNetPhysicalPath = propertyValue; } else if (str2 == "AspNetCompiler.TargetPath") { compilerParameters.aspNetTargetPath = propertyValue; } else if (str2 == "AspNetCompiler.ForceOverwrite") { compilerParameters.aspNetForce = propertyValue; } else if (str2 == "AspNetCompiler.Updateable") { compilerParameters.aspNetUpdateable = propertyValue; } else if (str2 == "AspNetCompiler.Debug") { compilerParameters.aspNetDebug = propertyValue; } else if (str2 == "AspNetCompiler.KeyFile") { compilerParameters.aspNetKeyFile = propertyValue; } else if (str2 == "AspNetCompiler.KeyContainer") { compilerParameters.aspNetKeyContainer = propertyValue; } else if (str2 == "AspNetCompiler.DelaySign") { compilerParameters.aspNetDelaySign = propertyValue; } else if (str2 == "AspNetCompiler.AllowPartiallyTrustedCallers") { compilerParameters.aspNetAPTCA = propertyValue; } else if (str2 == "AspNetCompiler.FixedNames") { compilerParameters.aspNetFixedNames = propertyValue; } proj.AspNetConfigurations[(object)str1] = (object)compilerParameters; } else if (string.Compare(propertyName, "ProjectReferences", StringComparison.OrdinalIgnoreCase) == 0) { string str1 = propertyValue; char[] separator = new char[1]; int index = 0; int num1 = 59; separator[index] = (char)num1; int num2 = 1; foreach (string str2 in str1.Split(separator, (StringSplitOptions)num2)) { if (str2.IndexOf('|') != -1) { int startIndex = str2.IndexOf('{'); if (startIndex != -1) { int num3 = str2.IndexOf('}', startIndex); if (num3 != -1) { string str3 = str2.Substring(startIndex, num3 - startIndex + 1); proj.Dependencies.Add((object)str3); proj.ProjectReferences.Add((object)str3); } } } } } else { if (string.Compare(propertyName, "TargetFrameworkMoniker", StringComparison.OrdinalIgnoreCase) != 0) { return; } string escapedString = this.TrimQuotes(propertyValue); proj.TargetFrameworkMoniker = (escapedString); } }
/// <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); } }
/// <summary> /// Add a PropertyGroup to the project for a particular Asp.Net configuration. This PropertyGroup /// will have the correct values for all the Asp.Net properties for this project and this configuration. /// </summary> private void AddPropertyGroupForAspNetConfiguration ( ProjectInstance traversalProject, ProjectInstance metaprojectInstance, ProjectInSolution project, string configurationName, AspNetCompilerParameters aspNetCompilerParameters, string solutionFile ) { // If the configuration doesn't match, don't add the properties. if (!traversalProject.EvaluateCondition(String.Format(CultureInfo.InvariantCulture, " '$(AspNetConfiguration)' == '{0}' ", EscapingUtilities.Escape(configurationName)))) { return; } // Add properties into the property group for each of the AspNetCompiler properties. // REVIEW: SetProperty takes an evaluated value. Are we doing the right thing here? metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetVirtualPath"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetVirtualPath)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetPhysicalPath"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetPhysicalPath)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetTargetPath"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetTargetPath)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetForce"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetForce)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetUpdateable"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetUpdateable)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetDebug"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetDebug)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetKeyFile"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetKeyFile)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetKeyContainer"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetKeyContainer)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetDelaySign"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetDelaySign)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetAPTCA"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetAPTCA)); metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetFixedNames"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetFixedNames)); string aspNetPhysicalPath = aspNetCompilerParameters.aspNetPhysicalPath; if (!String.IsNullOrEmpty(aspNetPhysicalPath)) { // Trim the trailing slash if one exists. if ( (aspNetPhysicalPath[aspNetPhysicalPath.Length - 1] == Path.AltDirectorySeparatorChar) || (aspNetPhysicalPath[aspNetPhysicalPath.Length - 1] == Path.DirectorySeparatorChar) ) { aspNetPhysicalPath = aspNetPhysicalPath.Substring(0, aspNetPhysicalPath.Length - 1); } // This gets us the last folder in the physical path. string lastFolderInPhysicalPath = null; try { lastFolderInPhysicalPath = Path.GetFileName(aspNetPhysicalPath); } catch (Exception e) { if (ExceptionHandling.NotExpectedException(e)) { throw; } ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile ( false, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(solutionFile), e, "SolutionParseInvalidProjectFileName", project.RelativePath, e.Message ); } if (!String.IsNullOrEmpty(lastFolderInPhysicalPath)) { // If there is a global property called "OutDir" set, that means the caller is trying to // override the AspNetTargetPath. What we want to do in this case is concatenate: // $(OutDir) + "\_PublishedWebsites" + (the last portion of the folder in the AspNetPhysicalPath). if (traversalProject.EvaluateCondition(" '$(OutDir)' != '' ")) { string outDirValue = String.Empty; ProjectPropertyInstance outdir = metaprojectInstance.GetProperty("OutDir"); if (outdir != null) { outDirValue = ProjectInstance.GetPropertyValueEscaped(outdir); } // Make sure the path we are appending to has no leading slash to prevent double slashes. string publishWebsitePath = EscapingUtilities.Escape(WebProjectOverrideFolder) + Path.DirectorySeparatorChar + EscapingUtilities.Escape(lastFolderInPhysicalPath) + Path.DirectorySeparatorChar; metaprojectInstance.SetProperty ( GenerateSafePropertyName(project, "AspNetTargetPath"), outDirValue + publishWebsitePath ); } } } }
/// <summary> /// When adding a target to build a web project, we want to put a Condition on the Target node that /// effectively says "Only build this target if the web project is active (marked for building) in the /// current solution configuration. /// </summary> private string ComputeTargetConditionForWebProject(ProjectInSolution project) { StringBuilder condition = new StringBuilder(" ('$(CurrentSolutionConfigurationContents)' != '') and (false"); // Loop through all the solution configurations. foreach (SolutionConfigurationInSolution solutionConfiguration in _solutionFile.SolutionConfigurations) { // Find out if the web project has a project configuration for this solution configuration. // (Actually, web projects only have one project configuration, so the TryGetValue should // pretty much always return "true". ProjectConfigurationInSolution projectConfiguration = null; if (project.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out projectConfiguration)) { // See if the web project is marked as active for this solution configuration. If so, // we'll build the target. Otherwise not. if (projectConfiguration.IncludeInBuild) { condition.Append(" or ("); condition.Append(GetConditionStringForConfiguration(solutionConfiguration)); condition.Append(")"); } } else if (String.Compare(solutionConfiguration.ConfigurationName, "Release", StringComparison.OrdinalIgnoreCase) == 0 || String.Compare(solutionConfiguration.ConfigurationName, "Debug", StringComparison.OrdinalIgnoreCase) == 0) { // we don't have a project configuration that matches the solution configuration but // the solution configuration is called "Release" or "Debug" which are standard AspNetConfigurations // so these should be available in the solution project condition.Append(" or ("); condition.Append(GetConditionStringForConfiguration(solutionConfiguration)); condition.Append(")"); } } condition.Append(") "); return condition.ToString(); }