Exemple #1
0
        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;
        }
Exemple #2
0
 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;
         }
     }
 }
Exemple #3
0
 //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);
 }
Exemple #4
0
 private void AddProjectToSolution(ProjectInSolution proj)
 {
     if (!string.IsNullOrEmpty(proj.ProjectGuid))
     {
         this.projects[(object)proj.ProjectGuid] = (object)proj;
     }
     this.projectsInOrder.Add((object)proj);
 }
Exemple #5
0
        internal string GetProjectUniqueNameByGuid(string projectGuid)
        {
            ProjectInSolution projectInSolution = (ProjectInSolution)this.projects[(object)projectGuid];

            if (projectInSolution != null)
            {
                return(projectInSolution.GetUniqueProjectName());
            }
            return((string)null);
        }
Exemple #6
0
        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;
        }
Exemple #10
0
        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);
        }
Exemple #15
0
 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;
 }
Exemple #20
0
        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
                 );
         }
     }
 }
Exemple #33
0
        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);
        }
Exemple #37
0
        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();
        }