示例#1
0
        /// <summary>
        /// 
        /// This method processes a "Project" section in the solution file opened by the specified
        /// StreamReader, and returns a populated ProjectInSolution instance, if successful.
        /// An exception is thrown if the solution file is invalid.
        ///
        /// The format of the parts of a Project section that we care about is as follows:
        ///
        ///  Project("{Project type GUID}") = "Project name", "Relative path to project file", "{Project GUID}"
        ///      ProjectSection(ProjectDependencies) = postProject
        ///          {Parent project unique name} = {Parent project unique name}
        ///          ...
        ///      EndProjectSection
        ///  EndProject
        /// 
        /// </summary>
        /// <param name="firstLine"></param>
        /// <returns></returns>
        private void ParseProject(string firstLine)
        {
            ErrorUtilities.VerifyThrow((firstLine != null) && (firstLine.Length != 0), "ParseProject() got a null firstLine!");
            ErrorUtilities.VerifyThrow(_reader != null, "ParseProject() got a null reader!");

            ProjectInSolution proj = new ProjectInSolution(this);

            // Extract the important information from the first line.
            ParseFirstProjectLine(firstLine, proj);

            // Search for project dependencies.  Keeping reading lines until we either 1.) reach
            // the end of the file, 2.) see "ProjectSection(ProjectDependencies)" at the beginning
            // of the line, or 3.) see "EndProject" at the beginning of the line.
            string line;
            while ((line = ReadLine()) != null)
            {
                // If we see an "EndProject", well ... that's the end of this project!
                if (line == "EndProject")
                {
                    break;
                }
                else if (line.StartsWith("ProjectSection(ProjectDependencies)", StringComparison.Ordinal))
                {
                    // We have a ProjectDependencies section.  Each subsequent line should identify
                    // a dependency.
                    line = ReadLine();
                    while ((line != null) && (!line.StartsWith("EndProjectSection", StringComparison.Ordinal)))
                    {
                        // This should be a dependency.  The GUID identifying the parent project should
                        // be both the property name and the property value.
                        Match match = s_crackPropertyLine.Value.Match(line);
                        ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(match.Success, "SubCategoryForSolutionParsingErrors",
                            new BuildEventFileInfo(FullPath, _currentLineNumber, 0), "SolutionParseProjectDepGuidError", proj.ProjectName);

                        string parentGuid = match.Groups["PROPERTYNAME"].Value.Trim();
                        proj.AddDependency(parentGuid);

                        line = ReadLine();
                    }
                }
                else if (line.StartsWith("ProjectSection(WebsiteProperties)", StringComparison.Ordinal))
                {
                    // We have a WebsiteProperties section.  This section is present only in Venus
                    // projects, and contains properties that we'll need in order to call the 
                    // AspNetCompiler task.
                    line = ReadLine();
                    while ((line != null) && (!line.StartsWith("EndProjectSection", StringComparison.Ordinal)))
                    {
                        Match match = s_crackPropertyLine.Value.Match(line);
                        ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(match.Success, "SubCategoryForSolutionParsingErrors",
                            new BuildEventFileInfo(FullPath, _currentLineNumber, 0), "SolutionParseWebProjectPropertiesError", proj.ProjectName);

                        string propertyName = match.Groups["PROPERTYNAME"].Value.Trim();
                        string propertyValue = match.Groups["PROPERTYVALUE"].Value.Trim();

                        ParseAspNetCompilerProperty(proj, propertyName, propertyValue);

                        line = ReadLine();
                    }
                }
            }

            ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(line != null, "SubCategoryForSolutionParsingErrors",
                new BuildEventFileInfo(FullPath), "SolutionParseProjectEofError", proj.ProjectName);

            // Add the project to the collection
            AddProjectToSolution(proj);
            // If the project is an etp project then parse the etp project file 
            // to get the projects contained in it.
            if (IsEtpProjectFile(proj.RelativePath))
            {
                ParseEtpProject(proj);
            }
        } // ParseProject()
 /// <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
                 );
         }
     }
 }
示例#3
0
        /// <summary>
        /// Takes a property name / value that comes from the SLN file for a Venus project, and
        /// stores it appropriately in our data structures.
        /// </summary>
        /// <param name="proj"></param>
        /// <param name="propertyName"></param>
        /// <param name="propertyValue"></param>
        private void ParseAspNetCompilerProperty
            (
            ProjectInSolution proj,
            string propertyName,
            string propertyValue
            )
        {
            // What we expect to find in the SLN file is something that looks like this:
            //
            // Project("{E24C65DC-7377-472B-9ABA-BC803B73C61A}") = "c:\...\myfirstwebsite\", "..\..\..\..\..\..\rajeev\temp\websites\myfirstwebsite", "{956CC04E-FD59-49A9-9099-96888CB6F366}"
            //     ProjectSection(WebsiteProperties) = preProject
            //       TargetFrameworkMoniker = ".NETFramework,Version%3Dv4.0"
            //       ProjectReferences = "{FD705688-88D1-4C22-9BFF-86235D89C2FC}|CSClassLibrary1.dll;{F0726D09-042B-4A7A-8A01-6BED2422BD5D}|VCClassLibrary1.dll;" 
            //       Debug.AspNetCompiler.VirtualPath = "/publishfirst"
            //       Debug.AspNetCompiler.PhysicalPath = "..\..\..\..\..\..\rajeev\temp\websites\myfirstwebsite\"
            //       Debug.AspNetCompiler.TargetPath = "..\..\..\..\..\..\rajeev\temp\publishfirst\"
            //       Debug.AspNetCompiler.ForceOverwrite = "true"
            //       Debug.AspNetCompiler.Updateable = "true"
            //       Debug.AspNetCompiler.Enabled = "true"
            //       Debug.AspNetCompiler.Debug = "true"
            //       Debug.AspNetCompiler.KeyFile = ""
            //       Debug.AspNetCompiler.KeyContainer = ""
            //       Debug.AspNetCompiler.DelaySign = "true"
            //       Debug.AspNetCompiler.AllowPartiallyTrustedCallers = "true"
            //       Debug.AspNetCompiler.FixedNames = "true"
            //       Release.AspNetCompiler.VirtualPath = "/publishfirst"
            //       Release.AspNetCompiler.PhysicalPath = "..\..\..\..\..\..\rajeev\temp\websites\myfirstwebsite\"
            //       Release.AspNetCompiler.TargetPath = "..\..\..\..\..\..\rajeev\temp\publishfirst\"
            //       Release.AspNetCompiler.ForceOverwrite = "true"
            //       Release.AspNetCompiler.Updateable = "true"
            //       Release.AspNetCompiler.Enabled = "true"
            //       Release.AspNetCompiler.Debug = "false"
            //       Release.AspNetCompiler.KeyFile = ""
            //       Release.AspNetCompiler.KeyContainer = ""
            //       Release.AspNetCompiler.DelaySign = "true"
            //       Release.AspNetCompiler.AllowPartiallyTrustedCallers = "true"
            //       Release.AspNetCompiler.FixedNames = "true"
            //     EndProjectSection
            // EndProject
            //
            // This method is responsible for parsing each of the lines within the "WebsiteProperties" section.
            // The first component of each property name is actually the configuration for which that
            // property applies.

            int indexOfFirstDot = propertyName.IndexOf('.');
            if (indexOfFirstDot != -1)
            {
                // The portion before the first dot is the configuration name.
                string configurationName = propertyName.Substring(0, indexOfFirstDot);

                // The rest of it is the actual property name.
                string aspNetPropertyName = ((propertyName.Length - indexOfFirstDot) > 0) ? propertyName.Substring(indexOfFirstDot + 1, propertyName.Length - indexOfFirstDot - 1) : "";

                // And the part after the <equals> sign is the property value (which was parsed out for us prior
                // to calling this method).
                propertyValue = TrimQuotes(propertyValue);

                // Grab the parameters for this specific configuration if they exist.
                object aspNetCompilerParametersObject = proj.AspNetConfigurations[configurationName];
                AspNetCompilerParameters aspNetCompilerParameters;

                if (aspNetCompilerParametersObject == null)
                {
                    // If it didn't exist, create a new one.
                    aspNetCompilerParameters = new AspNetCompilerParameters();
                    aspNetCompilerParameters.aspNetVirtualPath = String.Empty;
                    aspNetCompilerParameters.aspNetPhysicalPath = String.Empty;
                    aspNetCompilerParameters.aspNetTargetPath = String.Empty;
                    aspNetCompilerParameters.aspNetForce = String.Empty;
                    aspNetCompilerParameters.aspNetUpdateable = String.Empty;
                    aspNetCompilerParameters.aspNetDebug = String.Empty;
                    aspNetCompilerParameters.aspNetKeyFile = String.Empty;
                    aspNetCompilerParameters.aspNetKeyContainer = String.Empty;
                    aspNetCompilerParameters.aspNetDelaySign = String.Empty;
                    aspNetCompilerParameters.aspNetAPTCA = String.Empty;
                    aspNetCompilerParameters.aspNetFixedNames = String.Empty;
                }
                else
                {
                    // Otherwise just unbox it.
                    aspNetCompilerParameters = (AspNetCompilerParameters)aspNetCompilerParametersObject;
                }

                // Update the appropriate field within the parameters struct.
                if (aspNetPropertyName == "AspNetCompiler.VirtualPath")
                {
                    aspNetCompilerParameters.aspNetVirtualPath = propertyValue;
                }
                else if (aspNetPropertyName == "AspNetCompiler.PhysicalPath")
                {
                    aspNetCompilerParameters.aspNetPhysicalPath = propertyValue;
                }
                else if (aspNetPropertyName == "AspNetCompiler.TargetPath")
                {
                    aspNetCompilerParameters.aspNetTargetPath = propertyValue;
                }
                else if (aspNetPropertyName == "AspNetCompiler.ForceOverwrite")
                {
                    aspNetCompilerParameters.aspNetForce = propertyValue;
                }
                else if (aspNetPropertyName == "AspNetCompiler.Updateable")
                {
                    aspNetCompilerParameters.aspNetUpdateable = propertyValue;
                }
                else if (aspNetPropertyName == "AspNetCompiler.Debug")
                {
                    aspNetCompilerParameters.aspNetDebug = propertyValue;
                }
                else if (aspNetPropertyName == "AspNetCompiler.KeyFile")
                {
                    aspNetCompilerParameters.aspNetKeyFile = propertyValue;
                }
                else if (aspNetPropertyName == "AspNetCompiler.KeyContainer")
                {
                    aspNetCompilerParameters.aspNetKeyContainer = propertyValue;
                }
                else if (aspNetPropertyName == "AspNetCompiler.DelaySign")
                {
                    aspNetCompilerParameters.aspNetDelaySign = propertyValue;
                }
                else if (aspNetPropertyName == "AspNetCompiler.AllowPartiallyTrustedCallers")
                {
                    aspNetCompilerParameters.aspNetAPTCA = propertyValue;
                }
                else if (aspNetPropertyName == "AspNetCompiler.FixedNames")
                {
                    aspNetCompilerParameters.aspNetFixedNames = propertyValue;
                }

                // Store the updated parameters struct back into the hashtable by configuration name.
                proj.AspNetConfigurations[configurationName] = aspNetCompilerParameters;
            }
            else
            {
                // ProjectReferences = "{FD705688-88D1-4C22-9BFF-86235D89C2FC}|CSClassLibrary1.dll;{F0726D09-042B-4A7A-8A01-6BED2422BD5D}|VCClassLibrary1.dll;" 
                if (string.Compare(propertyName, "ProjectReferences", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    string[] projectReferenceEntries = propertyValue.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);

                    foreach (string projectReferenceEntry in projectReferenceEntries)
                    {
                        int indexOfBar = projectReferenceEntry.IndexOf('|');

                        // indexOfBar could be -1 if we had semicolons in the file names, so skip entries that 
                        // don't contain a guid. File names may not contain the '|' character
                        if (indexOfBar != -1)
                        {
                            int indexOfOpeningBrace = projectReferenceEntry.IndexOf('{');
                            if (indexOfOpeningBrace != -1)
                            {
                                int indexOfClosingBrace = projectReferenceEntry.IndexOf('}', indexOfOpeningBrace);
                                if (indexOfClosingBrace != -1)
                                {
                                    string referencedProjectGuid = projectReferenceEntry.Substring(indexOfOpeningBrace,
                                        indexOfClosingBrace - indexOfOpeningBrace + 1);

                                    proj.AddDependency(referencedProjectGuid);
                                    proj.ProjectReferences.Add(referencedProjectGuid);
                                }
                            }
                        }
                    }
                }
                else if (String.Compare(propertyName, "TargetFrameworkMoniker", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    //Website project need to back support 3.5 msbuild parser for the Blend (it is not move to .Net4.0 yet.)
                    //However, 3.5 version of Solution parser can't handle a equal sign in the value.  
                    //The "=" in targetframeworkMoniker was escaped to "%3D" for Orcas
                    string targetFrameworkMoniker = TrimQuotes(propertyValue);
                    proj.TargetFrameworkMoniker = Microsoft.Build.Shared.EscapingUtilities.UnescapeAll(targetFrameworkMoniker);
                }
            }
        }