Exemplo n.º 1
0
        /// <summary>
        /// Find the unique name for this project, e.g. SolutionFolder\SubSolutionFolder\ProjectName
        /// </summary>
        /// <owner>RGoel</owner>
        internal string GetUniqueProjectName()
        {
            if (this.uniqueProjectName == null)
            {
                // EtpSubProject and Venus projects have names that are already unique.  No need to prepend the SLN folder.
                if ((this.ProjectType == SolutionProjectType.WebProject) || (this.ProjectType == SolutionProjectType.EtpSubProject))
                {
                    this.uniqueProjectName = CleanseProjectName(this.ProjectName);
                }
                else
                {
                    // This is "normal" project, which in this context means anything non-Venus and non-EtpSubProject.

                    // If this project has a parent SLN folder, first get the full unique name for the SLN folder,
                    // and tack on trailing backslash.
                    string uniqueName = String.Empty;

                    if (this.ParentProjectGuid != null)
                    {
                        ProjectInSolution proj = (ProjectInSolution)this.ParentSolution.ProjectsByGuid[this.ParentProjectGuid];

                        ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(proj != null, "SubCategoryForSolutionParsingErrors",
                                                                                new BuildEventFileInfo(parentSolution.SolutionFile), "SolutionParseNestedProjectError");

                        uniqueName = proj.GetUniqueProjectName() + "\\";
                    }

                    // Now tack on our own project name, and cache it in the ProjectInSolution object for future quick access.
                    this.uniqueProjectName = CleanseProjectName(uniqueName + this.ProjectName);
                }
            }

            return(this.uniqueProjectName);
        }
Exemplo n.º 2
0
        public void ParseFirstProjectLineWithDifferentSpacing()
        {
            SolutionParser p = new SolutionParser();
            p.SolutionFile = "foobar.sln";
            ProjectInSolution proj = new ProjectInSolution(p);

            p.ParseFirstProjectLine
            (
                "Project(\" {Project GUID} \")  = \" Project name \",  \" Relative path to project file \"    , \" Unique name-GUID \"", 
                 proj
            );
            Assertion.AssertEquals(SolutionProjectType.Unknown, proj.ProjectType);
            Assertion.AssertEquals("Project name", proj.ProjectName);
            Assertion.AssertEquals("Relative path to project file", proj.RelativePath);
            Assertion.AssertEquals("Unique name-GUID", proj.ProjectGuid);
        }
Exemplo n.º 3
0
 /// <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>
 /// <param name="proj"></param>
 /// <param name="propertyName"></param>
 /// <returns>A safe property name that can be used as an XML element name.</returns>
 /// <owner>RGoel</owner>
 static private 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;
 }
Exemplo n.º 4
0
        /// <summary>
        /// Add a target for a Venus project into the XML doc that's being generated.  This
        /// target will call the AspNetCompiler task.
        /// </summary>
        /// <param name="msbuildProject"></param>
        /// <param name="solution"></param>
        /// <param name="proj"></param>
        /// <param name="subTargetName"></param>
        /// <owner>RGoel</owner>
        static private void AddTargetForWebProject
        (
            Project msbuildProject,
            SolutionParser solution,
            ProjectInSolution proj,
            string subTargetName
        )
        {
            // Add a supporting target called "GetFrameworkPathAndRedistList".
            AddTargetForGetFrameworkPathAndRedistList(msbuildProject);

            string targetName = ProjectInSolution.DisambiguateProjectTargetName(proj.GetUniqueProjectName());
            if (subTargetName != null && subTargetName.Length > 0)
            {
                targetName = targetName + ":" + subTargetName;
            }

            Target newTarget = msbuildProject.Targets.AddNewTarget(targetName);

            newTarget.DependsOnTargets = GetProjectDependencies(proj.ParentSolution, proj, subTargetName) + ";GetFrameworkPathAndRedistList";

            if (subTargetName == "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.
                AddErrorWarningMessageElement(newTarget, XMakeElements.message, true, "SolutionVenusProjectNoClean");
            }
            else if (subTargetName == "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.
                AddErrorWarningMessageElement(newTarget, XMakeElements.message, true, "SolutionVenusProjectNoPublish");
            }
            else
            {
                // Add a Condition onto the Target that will cause it only to get executed for those solution configurations
                // in which this web project is active.
                newTarget.Condition = ComputeTargetConditionForWebProject(solution, proj);

                // 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 proj.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 (subTargetName == null)
                    {
                        AddPropertyGroupForAspNetConfiguration(msbuildProject, proj, configurationName, 
                            aspNetCompilerParameters, solution.SolutionFile);
                    }

                    // 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(proj, "References"));
                if (!string.IsNullOrEmpty(subTargetName))
                {
                    referenceItemName.Append('_');
                    referenceItemName.Append(subTargetName);
                }

                // Add tasks to resolve project references of this web project, if any
                if (proj.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 (ConfigurationInSolution solutionConfiguration in solution.SolutionConfigurations)
                    {
                        string referenceProjectGuids = null;

                        AddResolveProjectReferenceTasks(solution, msbuildProject, newTarget, proj, 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, proj, referenceItemName.ToString());

                // Add a call to RAR (ResolveAssemblyReference) and the Copy task to put the referenced 
                // project outputs in the right place
                AddTasksToCopyAllDependenciesIntoBinDir(newTarget, proj, referenceItemName.ToString(), conditionDescribingValidConfigurations.ToString());

                // Add a call to the AspNetCompiler task, conditioned on having a valid Configuration.
                AddTaskForAspNetCompiler(newTarget, proj, 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.
                BuildTask newMessageTag = AddErrorWarningMessageElement(newTarget, XMakeElements.message, false, "SolutionVenusProjectSkipped");
                newMessageTag.Condition = "!(" + conditionDescribingValidConfigurations.ToString() + ")";
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Add a target for a project into the XML doc that's being generated.
        /// </summary>
        /// <param name="msbuildProject"></param>
        /// <param name="solution"></param>
        /// <param name="proj"></param>
        /// <param name="subTargetName"></param>
        /// <owner>LukaszG, RGoel</owner>
        static private void AddTargetForVCProject
        (
            Project msbuildProject,
            SolutionParser solution,
            ProjectInSolution proj,
            string subTargetName
        )
        {
            string targetName = ProjectInSolution.DisambiguateProjectTargetName(proj.GetUniqueProjectName());
            if (subTargetName != null && subTargetName.Length > 0)
            {
                targetName = targetName + ":" + subTargetName;
            }

            Target newTarget = msbuildProject.Targets.AddNewTarget(targetName);
            newTarget.DependsOnTargets = GetProjectDependencies(proj.ParentSolution, proj, subTargetName);
            newTarget.Condition = "'$(CurrentSolutionConfigurationContents)' != ''";

            if (subTargetName == "Publish")
            {
                // Well, hmmm.  The VCBuild doesn't support any kind of 
                // a "Publish" operation.  The best we can really do is offer up a 
                // message saying so.
                AddErrorWarningMessageElement(newTarget, XMakeElements.warning, true, "SolutionVCProjectNoPublish");

                // ... and now pretend it's a Build subtarget. This way references to VC projects from projects
                // that are about to publish will at least get built.
                subTargetName = null;
            }

            string projectPath = null;

            try
            {
                projectPath = proj.AbsolutePath;
            }
            catch (Exception e)
            {
                if (ExceptionHandling.NotExpectedException(e))
                    throw;

                ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(false,
                    "SubCategoryForSolutionParsingErrors",
                    new BuildEventFileInfo(solution.SolutionFile),
                    "SolutionParseInvalidProjectFileName",
                    proj.RelativePath, e.Message);
            }

            foreach (ConfigurationInSolution solutionConfiguration in solution.SolutionConfigurations)
            {
                string solutionConfigurationCondition = GetConditionStringForConfiguration(solutionConfiguration);

                ProjectConfigurationInSolution vcProjectConfiguration = null;
                BuildTask newTask = null;

                if (proj.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out vcProjectConfiguration))
                {
                    if (vcProjectConfiguration.IncludeInBuild)
                    {
                        // Create a temporary VC project with references to MSBuild projects replaced with file references.
                        if (proj.ProjectReferences.Count > 0)
                        {
                            projectPath = AddCreateTemporaryVCProjectTasks(solution, msbuildProject, newTarget, proj,
                                solutionConfiguration, subTargetName, 
                                vcProjectConfiguration.FullName);
                        }

                        newTask = VCWrapperProject.AddVCBuildTaskElement(
                            msbuildProject,
                            newTarget,
                            EscapingUtilities.Escape(Path.Combine(solution.SolutionFileDirectory, Path.GetFileName(solution.SolutionFile))), 
                            projectPath, subTargetName, 
                            null, EscapingUtilities.Escape(vcProjectConfiguration.FullName));

                        // Delete the temporary VC project
                        if (proj.ProjectReferences.Count > 0)
                        {
                            BuildTask deleteTask = newTarget.AddNewTask("Delete");
                            deleteTask.SetParameterValue("Files", projectPath, true /* treat as literal */);

                            deleteTask.Condition = solutionConfigurationCondition;
                        }
                    }
                    else
                    {
                        newTask = AddErrorWarningMessageElement(newTarget, XMakeElements.message, true, "SolutionProjectSkippedForBuilding", proj.ProjectName, solutionConfiguration.FullName);
                    }
                }
                else
                {
                    newTask = AddErrorWarningMessageElement(newTarget, XMakeElements.warning, true, "SolutionProjectConfigurationMissing", proj.ProjectName, solutionConfiguration.FullName);
                }

                if (newTask != null)
                {
                    newTask.Condition = solutionConfigurationCondition;
                }
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Adds MSBuild and ResolveVCProjectOutput tasks to a project target to pre-resolve its project references
        /// </summary>
        /// <param name="solution"></param>
        /// <param name="target"></param>
        /// <param name="proj"></param>
        /// <param name="solutionConfiguration"></param>
        /// <param name="outputReferenceItemName"></param>
        /// <param name="outputImportLibraryItemName"></param>
        /// <param name="addedReferenceGuids"></param>
        /// <owner>LukaszG</owner>
        static private void AddResolveProjectReferenceTasks
        (
            SolutionParser solution,
            Project msbuildProject,
            Target target,
            ProjectInSolution proj,
            ConfigurationInSolution 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/VC project references
            foreach (string projectReferenceGuid in proj.ProjectReferences)
            {
                ProjectInSolution referencedProject = (ProjectInSolution)solution.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);

                    bool addCreateItem = false;

                    if ((referencedProject.ProjectType == SolutionProjectType.ManagedProject) ||
                        ((referencedProject.ProjectType == SolutionProjectType.Unknown) && (referencedProject.CanBeMSBuildProjectFile(out message))))
                    {
                        string condition = GetConditionStringForConfiguration(solutionConfiguration);
                        bool specifyProjectToolsVersion =
                            String.Equals(msbuildProject.ToolsVersion, "2.0", StringComparison.OrdinalIgnoreCase) ? false : true;

                        BuildTask msbuildTask = AddMSBuildTaskElement(target, referencedProject.RelativePath, "GetTargetPath",
                            referencedProjectConfiguration.ConfigurationName, referencedProjectConfiguration.PlatformName, specifyProjectToolsVersion);
                        msbuildTask.Condition = condition;
                        msbuildTask.AddOutputItem("TargetOutputs", outputReferenceItemNameWithSuffix);                        

                        if (referenceGuids.Length > 0)
                        {
                            referenceGuids.Append(';');
                        }

                        referenceGuids.Append(projectReferenceGuid);
                        addCreateItem = true;

                    }
                    else if (referencedProject.ProjectType == SolutionProjectType.VCProject)
                    {
                        BuildTask vcbuildTask = null;

                        try
                        {
                            vcbuildTask = AddResolveVCProjectOutputTaskElement(target, Path.Combine(solution.SolutionFileDirectory, Path.GetFileName(solution.SolutionFile)),
                                referencedProject.AbsolutePath, referencedProjectConfiguration.FullName);
                        }
                        catch (Exception e)
                        {
                            if (ExceptionHandling.NotExpectedException(e))
                               throw;

                            ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(false,
                                "SubCategoryForSolutionParsingErrors",
                                new BuildEventFileInfo(solution.SolutionFile),
                                "SolutionParseInvalidProjectFileName",
                                referencedProject.RelativePath, e.Message);
                        }

                        vcbuildTask.Condition = GetConditionStringForConfiguration(solutionConfiguration);
                        vcbuildTask.AddOutputItem("ResolvedOutputPaths", outputReferenceItemNameWithSuffix);
                        
                        if (outputImportLibraryItemName != null)
                        {
                            vcbuildTask.AddOutputItem("ResolvedImportLibraryPaths", outputImportLibraryItemName);
                        }

                        if (referenceGuids.Length > 0)
                        {
                            referenceGuids.Append(';');
                        }

                        referenceGuids.Append(projectReferenceGuid);
                        addCreateItem = true;
                    }

                    // Add create item if either of the conditions above was true. 
                    // This merges the one-item item list into the main list, adding the appropriate guid metadata
                    if (addCreateItem)
                    {
                        BuildTask createItemTask = target.AddNewTask("CreateItem");
                        createItemTask.SetParameterValue("Include", "@(" + outputReferenceItemNameWithSuffix + ")", false /* do not treat as literal */);
                        createItemTask.SetParameterValue("AdditionalMetadata", "Guid=" + projectReferenceGuid, false /* do not treat as literal */);
                        createItemTask.AddOutputItem("Include", outputReferenceItemName);
                    }

                    outputReferenceItemNameSuffix++;
                }
            }

            addedReferenceGuids = referenceGuids.ToString();
        }
Exemplo n.º 7
0
        /// <summary>
        /// Recursive helper for AddVirtualReferencesForStaticLibraries
        /// </summary>
        private static void GatherChildReferencesForStaticLibraries(SolutionParser solution, ProjectInSolution project)
        {
            // We don't need to worry about cycles since we've already run the dependency level assignment
            // which already checked for them.
            if (!project.ChildReferencesGathered)
            {
                List<string> referenceGuidsToAdd = new List<string>();

                foreach (string referenceGuid in project.ProjectReferences)
                {
                    ProjectInSolution referencedProject = (ProjectInSolution)solution.ProjectsByGuid[referenceGuid];

                    // Gather references for all child projects recursively...
                    GatherChildReferencesForStaticLibraries(solution, referencedProject);

                    // ... and pass on references from any static lib children we have to ourselves
                    if (referencedProject.IsStaticLibrary)
                    {
                        foreach (string childReferenceGuid in referencedProject.ProjectReferences)
                        {
                            if (!project.ProjectReferences.Contains(childReferenceGuid) && 
                                !referenceGuidsToAdd.Contains(childReferenceGuid))
                            {
                                referenceGuidsToAdd.Add(childReferenceGuid);
                            }
                        }
                    }
                }

                project.ProjectReferences.AddRange(referenceGuidsToAdd);
                project.ChildReferencesGathered = true;
            }
        }
Exemplo n.º 8
0
 /// <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>
 /// <param name="solution">The solution in which the project exists</param>
 /// <param name="project">The project to which the dependency will be added</param>
 /// <param name="parentEngine">The engine handling the conversion</param>
 /// <param name="projectBuildEventContext">The build event context</param>
 /// <param name="dependencyGuid">The guid, in string form, of the dependency project</param>
 static private void AddDependencyByGuid(SolutionParser solution, ProjectInSolution project, Engine parentEngine, BuildEventContext projectBuildEventContext, string dependencyGuid)
 {
     if (!String.IsNullOrEmpty(dependencyGuid))
     {
         if (solution.ProjectsByGuid.ContainsKey(dependencyGuid))
         {
             project.Dependencies.Add(dependencyGuid);
         }
         else
         {
             parentEngine.LoggingServices.LogWarning(projectBuildEventContext, "SubCategoryForSolutionParsingErrors", new BuildEventFileInfo(solution.SolutionFile),
                 "SolutionParseProjectDepNotFoundError", project.ProjectGuid, dependencyGuid);
         }
     }
 }
Exemplo n.º 9
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>
        /// <owner>RGoel</owner>
        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
            //       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.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[] { ';' });

                    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('{');
                            int indexOfClosingBrace = projectReferenceEntry.IndexOf('}', indexOfOpeningBrace);

                            // Cut out the guid part
                            if ((indexOfOpeningBrace != -1) && (indexOfClosingBrace != -1))
                            {
                                string referencedProjectGuid = projectReferenceEntry.Substring(indexOfOpeningBrace, 
                                    indexOfClosingBrace - indexOfOpeningBrace + 1);

                                proj.Dependencies.Add(referencedProjectGuid);
                                proj.ProjectReferences.Add(referencedProjectGuid);
                            }
                        }
                    }
                }
            }
        }
Exemplo n.º 10
0
        /// <summary>
        /// Validate relative path of a project
        /// </summary>
        /// <param name="proj">proj</param>
        private void ValidateProjectRelativePath(ProjectInSolution proj)
        {
            // Verify the relative path is not null
            ErrorUtilities.VerifyThrow(proj.RelativePath != null, "Project relative path cannot be null.");

            // Verify the relative path does not contain invalid characters
            ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(proj.RelativePath.IndexOfAny(Path.GetInvalidPathChars()) == -1,
              "SubCategoryForSolutionParsingErrors",
              new BuildEventFileInfo(SolutionFile, this.currentLineNumber, 0),
              "SolutionParseInvalidProjectFileNameCharacters",
              proj.ProjectName, proj.RelativePath);

            // Verify the relative path is not empty string
            ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(proj.RelativePath.Length > 0,
                  "SubCategoryForSolutionParsingErrors",
                  new BuildEventFileInfo(SolutionFile, this.currentLineNumber, 0),
                  "SolutionParseInvalidProjectFileNameEmpty",
                  proj.ProjectName);
        }
Exemplo n.º 11
0
 /// <summary>
 /// Adds a given project to the project collections of this class
 /// </summary>
 /// <param name="proj">proj</param>
 private void AddProjectToSolution(ProjectInSolution proj)
 {
     if (!String.IsNullOrEmpty(proj.ProjectGuid))
     {
         projects[proj.ProjectGuid] = proj;
     }
     projectsInOrder.Add(proj);
 }
Exemplo n.º 12
0
        } // ParseProject()

        /// <summary>
        /// This method will parse a .etp project recursively and 
        /// add all the projects found to projects and projectsInOrder
        /// </summary>
        /// <param name="etpProj">ETP Project</param>
        internal void ParseEtpProject(ProjectInSolution etpProj)
        {
            XmlDocument etpProjectDocument = new XmlDocument();
            // Get the full path to the .etp project file
            string fullPathToEtpProj = Path.Combine(solutionFileDirectory, etpProj.RelativePath);
            string etpProjectRelativeDir = Path.GetDirectoryName(etpProj.RelativePath);
            try
            {
                /****************************************************************************
                * A Typical .etp project file will look like this
                *<?xml version="1.0"?>
                *<EFPROJECT>
                *    <GENERAL>
                *        <BANNER>Microsoft Visual Studio Application Template File</BANNER>
                *        <VERSION>1.00</VERSION>
                *        <Views>
                *            <ProjectExplorer>
                *                <File>ClassLibrary2\ClassLibrary2.csproj</File>
                *            </ProjectExplorer>
                *        </Views>
                *        <References>
                *            <Reference>
                *                <FILE>ClassLibrary2\ClassLibrary2.csproj</FILE>
                *                <GUIDPROJECTID>{73D0F4CE-D9D3-4E8B-81E4-B26FBF4CC2FE}</GUIDPROJECTID>
                *            </Reference>
                *        </References>
                *    </GENERAL>
                *</EFPROJECT>
                **********************************************************************************/
                // Make sure the XML reader ignores DTD processing
                XmlReaderSettings readerSettings = new XmlReaderSettings();
                readerSettings.DtdProcessing = DtdProcessing.Ignore;

                // Load the .etp project file thru the XML reader
                using (XmlReader xmlReader = XmlReader.Create(fullPathToEtpProj, readerSettings))
                {
                    etpProjectDocument.Load(xmlReader);
                }
                
                // We need to parse the .etp project file to get the names of projects contained
                // in the .etp Project. The projects are listed under /EFPROJECT/GENERAL/References/Reference node in the .etp project file.
                // The /EFPROJECT/GENERAL/Views/ProjectExplorer node will not necessarily contain 
                // all the projects in the .etp project. Therefore, we need to look at 
                // /EFPROJECT/GENERAL/References/Reference.
                // Find the /EFPROJECT/GENERAL/References/Reference node
                // Note that this is case sensitive
                XmlNodeList referenceNodes = etpProjectDocument.DocumentElement.SelectNodes("/EFPROJECT/GENERAL/References/Reference");
                // Do the right thing for each <REference> element
                foreach (XmlNode referenceNode in referenceNodes)
                {
                    // Get the relative path to the project file
                    string fileElementValue = referenceNode.SelectSingleNode("FILE").InnerText;
                    // If <FILE>  element is not present under <Reference> then we don't do anything.
                    if (fileElementValue != null)
                    {
                        // Create and populate a ProjectInSolution for the project
                        ProjectInSolution proj = new ProjectInSolution(this);
                        proj.RelativePath = Path.Combine(etpProjectRelativeDir, fileElementValue);

                        // Verify the relative path specified in the .etp proj file
                        ValidateProjectRelativePath(proj);
                        proj.ProjectType = SolutionProjectType.EtpSubProject;
                        proj.ProjectName = proj.RelativePath;
                        XmlNode projGuidNode = referenceNode.SelectSingleNode("GUIDPROJECTID");
                        if (projGuidNode != null)
                        {
                            proj.ProjectGuid = projGuidNode.InnerText;
                        }
                        // It is ok for a project to not have a guid inside an etp project.
                        // If a solution file contains a project without a guid it fails to 
                        // load in Everett. But if an etp project contains a project without 
                        // a guid it loads well in Everett and p2p references to/from this project
                        // are preserved. So we should make sure that we don�t error in this 
                        // situation while upgrading.
                        else
                        {
                            proj.ProjectGuid = String.Empty;
                        }
                        // Add the recently created proj to the collection of projects
                        AddProjectToSolution(proj);
                        // If the project is an etp project recurse
                        if (IsEtpProjectFile(fileElementValue))
                        {
                            ParseEtpProject(proj);
                        }
                    }
                }
            }
            // catch all sorts of exceptions - if we encounter any problems here, we just assume the .etp project file is not in the correct format

            // handle security errors
            catch (SecurityException e)
            {
                // Log a warning 
                string errorCode, ignoredKeyword;
                string warning = ResourceUtilities.FormatResourceString(out errorCode, out ignoredKeyword, "Shared.ProjectFileCouldNotBeLoaded",
                    etpProj.RelativePath, e.Message);
                solutionParserWarnings.Add(warning);
                solutionParserErrorCodes.Add(errorCode);
            }
            // handle errors in path resolution
            catch (NotSupportedException e)
            {
                // Log a warning 
                string errorCode, ignoredKeyword;
                string warning = ResourceUtilities.FormatResourceString(out errorCode, out ignoredKeyword, "Shared.ProjectFileCouldNotBeLoaded",
                    etpProj.RelativePath, e.Message);
                solutionParserWarnings.Add(warning);
                solutionParserErrorCodes.Add(errorCode);
            }
            // handle errors in loading project file
            catch (IOException e)
            {
                // Log a warning 
                string errorCode, ignoredKeyword;
                string warning = ResourceUtilities.FormatResourceString(out errorCode, out ignoredKeyword, "Shared.ProjectFileCouldNotBeLoaded",
                    etpProj.RelativePath, e.Message);
                solutionParserWarnings.Add(warning);
                solutionParserErrorCodes.Add(errorCode);
            }
            // handle errors in loading project file
            catch (UnauthorizedAccessException e)
            {
                // Log a warning 
                string errorCode, ignoredKeyword;
                string warning = ResourceUtilities.FormatResourceString(out errorCode, out ignoredKeyword, "Shared.ProjectFileCouldNotBeLoaded",
                    etpProj.RelativePath, e.Message);
                solutionParserWarnings.Add(warning);
                solutionParserErrorCodes.Add(errorCode);
            }
            // handle XML parsing errors 
            catch (XmlException e)
            {
                // Log a warning 
                string errorCode, ignoredKeyword;
                string warning = ResourceUtilities.FormatResourceString(out errorCode, out ignoredKeyword, "Shared.InvalidProjectFile",
                   etpProj.RelativePath, e.Message);
                solutionParserWarnings.Add(warning);
                solutionParserErrorCodes.Add(errorCode);
            }  
        }
Exemplo n.º 13
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>
        /// <owner>RGoel</owner>
        private void ParseProject(string firstLine)
        {
            error.VerifyThrow((firstLine != null) && (firstLine.Length != 0), "ParseProject() got a null firstLine!");
            error.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 = crackPropertyLine.Match(line);
                        ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(match.Success, "SubCategoryForSolutionParsingErrors",
                            new BuildEventFileInfo(SolutionFile, this.currentLineNumber, 0), "SolutionParseProjectDepGuidError", proj.ProjectName);

                        string parentGuid = match.Groups["PROPERTYNAME"].Value.Trim();
                        proj.Dependencies.Add(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 = crackPropertyLine.Match(line);
                        ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(match.Success, "SubCategoryForSolutionParsingErrors",
                            new BuildEventFileInfo(SolutionFile, this.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(SolutionFile), "SolutionParseProjectEofError", proj.ProjectName);

            if (proj != null)
            {
                // 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()
Exemplo n.º 14
0
        /// <summary>
        /// Parse the first line of a Project section of a solution file. This line should look like:
        ///
        ///  Project("{Project type GUID}") = "Project name", "Relative path to project file", "{Project GUID}"
        /// 
        /// </summary>
        /// <param name="firstLine"></param>
        /// <param name="proj"></param>
        /// <owner>RGoel</owner>
        internal void ParseFirstProjectLine
        (
            string firstLine,
            ProjectInSolution proj
        )
        {
            Match match = crackProjectLine.Match(firstLine);
            ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(match.Success, "SubCategoryForSolutionParsingErrors",
                new BuildEventFileInfo(SolutionFile, this.currentLineNumber, 0), "SolutionParseProjectError");

            string projectTypeGuid = 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();
            
            // Validate project relative path
            ValidateProjectRelativePath(proj);
            
            // Figure out what type of project this is.
            if ((String.Compare(projectTypeGuid, vbProjectGuid, StringComparison.OrdinalIgnoreCase) == 0) ||
                (String.Compare(projectTypeGuid, csProjectGuid, StringComparison.OrdinalIgnoreCase) == 0) ||
                (String.Compare(projectTypeGuid, vjProjectGuid, StringComparison.OrdinalIgnoreCase) == 0))
            {
                proj.ProjectType = SolutionProjectType.ManagedProject;
            }
            else if (String.Compare(projectTypeGuid, solutionFolderGuid, StringComparison.OrdinalIgnoreCase) == 0)
            {
                proj.ProjectType = SolutionProjectType.SolutionFolder;
            }
            else if (String.Compare(projectTypeGuid, vcProjectGuid, StringComparison.OrdinalIgnoreCase) == 0)
            {
                proj.ProjectType = SolutionProjectType.VCProject;
            }
            else if (String.Compare(projectTypeGuid, webProjectGuid, StringComparison.OrdinalIgnoreCase) == 0)
            {
                proj.ProjectType = SolutionProjectType.WebProject;
                solutionContainsWebProjects = true;
            }
            else
            {
                proj.ProjectType = SolutionProjectType.Unknown;
            }
        }
Exemplo n.º 15
0
        /// <summary>
        /// Emit warnings when the project type is unknown.
        /// </summary>
        /// <param name="msbuildProject">The project to add the target to</param>
        /// <param name="proj">The project to add as a target.</param>
        /// <param name="subTargetName">The target to call within the project that's being added.</param>
        /// <param name="errorMessage">Optional detailed error message to print out in case we already tried accessing the 
        /// project file before and failed.</param>
        /// <owner>RGoel</owner>
        static private void AddTargetForUnknownProjectType
        (
            Project msbuildProject,
            SolutionParser solution,
            ProjectInSolution proj,
            string subTargetName,
            string errorMessage
        )
        {
            string targetName = ProjectInSolution.DisambiguateProjectTargetName(proj.GetUniqueProjectName());
            if (subTargetName != null && subTargetName.Length > 0)
            {
                targetName = targetName + ":" + subTargetName;
            }

            Target newTarget = msbuildProject.Targets.AddNewTarget(targetName);
            newTarget.DependsOnTargets = GetProjectDependencies(proj.ParentSolution, proj, subTargetName);
            newTarget.Condition = "'$(CurrentSolutionConfigurationContents)' != ''";

            foreach (ConfigurationInSolution solutionConfiguration in solution.SolutionConfigurations)
            {
                ProjectConfigurationInSolution projectConfiguration = null;
                BuildTask newTask = null;

                if (proj.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out projectConfiguration))
                {
                    if (projectConfiguration.IncludeInBuild)
                    {
                        if (errorMessage == null)
                        {
                            // we haven't encountered any problems accessing the project file in the past, but do not support
                            // building this project type
                            newTask = AddErrorWarningMessageElement(newTarget, XMakeElements.warning, true, "SolutionParseUnknownProjectType", proj.RelativePath);
                        }
                        else
                        {
                            // this project file may be of supported type, but we have encountered problems accessing it
                            newTask = AddErrorWarningMessageElement(newTarget, XMakeElements.warning, true, "SolutionParseErrorReadingProject", proj.RelativePath, errorMessage);
                        }
                    }
                    else
                    {
                        newTask = AddErrorWarningMessageElement(newTarget, XMakeElements.message, true, "SolutionProjectSkippedForBuilding", proj.ProjectName, solutionConfiguration.FullName);
                    }
                }
                else
                {
                    newTask = AddErrorWarningMessageElement(newTarget, XMakeElements.warning, true, "SolutionProjectConfigurationMissing", proj.ProjectName, solutionConfiguration.FullName);
                }

                if (newTask != null)
                {
                    newTask.Condition = GetConditionStringForConfiguration(solutionConfiguration);
                }
            }
        }
Exemplo n.º 16
0
        /// <summary>
        /// This method returns a string containing a semicolon-separated list of "friendly" project names
        /// on which the specified project depends.  If the null is specified, a list of all projects
        /// is returned.
        /// </summary>
        /// <param name="solution"></param>
        /// <param name="project"></param>
        /// <param name="subTargetName"></param>
        /// <returns></returns>
        /// <owner>RGoel</owner>
        static private string GetProjectDependencies(SolutionParser solution, ProjectInSolution project, string subTargetName)
        {
            ErrorUtilities.VerifyThrow(project != null, "We should always have a project for this method");
            StringBuilder dependencies = new StringBuilder();

            // Get all the dependencies for this project
            foreach (string dependency in project.Dependencies)
            {
                if (dependencies.Length != 0)
                {
                    dependencies.Append(";");
                }

                string projectUniqueName = solution.GetProjectUniqueNameByGuid(dependency);
                ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(projectUniqueName != null,
                    "SubCategoryForSolutionParsingErrors",
                    new BuildEventFileInfo(solution.SolutionFile),
                    "SolutionParseProjectDepNotFoundError", project.ProjectGuid, dependency);

                dependencies.Append(ProjectInSolution.DisambiguateProjectTargetName(projectUniqueName));
                if (subTargetName != null && subTargetName.Length > 0)
                {
                    dependencies.Append(":");
                    dependencies.Append(subTargetName);
                }
            }

            return dependencies.ToString();
        }
Exemplo n.º 17
0
        /// <summary>
        /// Helper method to add a call to the AspNetCompiler task into the given target.
        /// </summary>
        /// <param name="target"></param>
        /// <param name="proj"></param>
        /// <param name="conditionDescribingValidConfigurations"></param>
        /// <owner>RGoel</owner>
        static private void AddTaskForAspNetCompiler
            (
            Target target,
            ProjectInSolution proj,
            string conditionDescribingValidConfigurations
            )
        {
            // Add a call to the AspNetCompiler task, conditioned on having a valid Configuration.
            BuildTask newTask = target.AddNewTask("AspNetCompiler");
            newTask.SetParameterValue("VirtualPath", "$(" + GenerateSafePropertyName(proj, "AspNetVirtualPath") + ")");
            newTask.SetParameterValue("PhysicalPath", "$(" + GenerateSafePropertyName(proj, "AspNetPhysicalPath") + ")");
            newTask.SetParameterValue("TargetPath", "$(" + GenerateSafePropertyName(proj, "AspNetTargetPath") + ")");
            newTask.SetParameterValue("Force", "$(" + GenerateSafePropertyName(proj, "AspNetForce") + ")");
            newTask.SetParameterValue("Updateable", "$(" + GenerateSafePropertyName(proj, "AspNetUpdateable") + ")");
            newTask.SetParameterValue("Debug", "$(" + GenerateSafePropertyName(proj, "AspNetDebug") + ")");
            newTask.SetParameterValue("KeyFile", "$(" + GenerateSafePropertyName(proj, "AspNetKeyFile") + ")");
            newTask.SetParameterValue("KeyContainer", "$(" + GenerateSafePropertyName(proj, "AspNetKeyContainer") + ")");
            newTask.SetParameterValue("DelaySign", "$(" + GenerateSafePropertyName(proj, "AspNetDelaySign") + ")");
            newTask.SetParameterValue("AllowPartiallyTrustedCallers", "$(" + GenerateSafePropertyName(proj, "AspNetAPTCA") + ")");
            newTask.SetParameterValue("FixedNames", "$(" + GenerateSafePropertyName(proj, "AspNetFixedNames") + ")");

            newTask.Condition = conditionDescribingValidConfigurations;
        }
Exemplo n.º 18
0
        /// <summary>
        /// Figure out the dependency level of the given project.
        /// </summary>
        /// <param name="project"></param>
        /// <param name="solution"></param>
        /// <param name="projectsByDependencyLevel"></param>
        static private void AssignDependencyLevel(ProjectInSolution project, SolutionParser solution, Dictionary<int, List<ProjectInSolution>> projectsByDependencyLevel)
        {
            // if we ever try to recurse into a project whose dependency level we're calculating above,
            // we have a circular dependency.
            if (project.DependencyLevel == ProjectInSolution.DependencyLevelBeingDetermined)
            {
                ProjectErrorUtilities.VerifyThrowInvalidProject(false, null, "SolutionCircularDependencyError", project.ProjectName);
            }

            if (project.DependencyLevel == ProjectInSolution.DependencyLevelUnknown)
            {
                project.DependencyLevel = ProjectInSolution.DependencyLevelBeingDetermined;

                int maxDependencyLevel = 0;

                // First, go through dependencies and ensure they have their dependency level set correctly.
                foreach (string dependencyGuid in project.Dependencies)
                {
                    ProjectInSolution referencedProject = (ProjectInSolution) solution.ProjectsByGuid[dependencyGuid];

                    AssignDependencyLevel(referencedProject, solution, projectsByDependencyLevel);

                    if (referencedProject.DependencyLevel + 1 > maxDependencyLevel)
                    {
                        maxDependencyLevel = referencedProject.DependencyLevel + 1;
                    }
                }

                // Our dependency level is the highest dependency level of all our dependencies plus 1, or 0 if we had
                // no dependencies.
                project.DependencyLevel = maxDependencyLevel;

                if (!projectsByDependencyLevel.ContainsKey(maxDependencyLevel))
                {
                    projectsByDependencyLevel.Add(maxDependencyLevel, new List<ProjectInSolution>());
                }

                projectsByDependencyLevel[maxDependencyLevel].Add(project);
            }
        }
Exemplo n.º 19
0
        /// <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>
        /// <param name="target"></param>
        /// <param name="proj"></param>
        /// <param name="referenceItemName"></param>
        /// <param name="conditionDescribingValidConfigurations"></param>
        /// <owner>RGoel</owner>
        static private void AddTasksToCopyAllDependenciesIntoBinDir
            (
            Target target, 
            ProjectInSolution proj, 
            string referenceItemName, 
            string conditionDescribingValidConfigurations
            )
        {
            string copyLocalFilesItemName = referenceItemName + "_CopyLocalFiles";
            string destinationFolder = String.Format(CultureInfo.InvariantCulture,
                @"$({0})\Bin\", GenerateSafePropertyName(proj, "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.
            BuildTask copyNonExistentReferencesTask = target.AddNewTask("Copy");
            copyNonExistentReferencesTask.SetParameterValue("SourceFiles", "@(" + referenceItemName + "->'%(FullPath)')", false /* Do not treat as literal */);
            copyNonExistentReferencesTask.SetParameterValue("DestinationFolder", destinationFolder);
            copyNonExistentReferencesTask.Condition = String.Format(CultureInfo.InvariantCulture, "!Exists('%({0}.Identity)')", referenceItemName);
            copyNonExistentReferencesTask.ContinueOnError = true;

            // 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.
            BuildTask rarTask = target.AddNewTask("ResolveAssemblyReference");
            rarTask.SetParameterValue("Assemblies", "@(" + referenceItemName + "->'%(FullPath)')", false /* Do not treat as literal */);
            rarTask.SetParameterValue("TargetFrameworkDirectories", "@(_CombinedTargetFrameworkDirectoriesItem)", false /* Do not treat as literal */);
            rarTask.SetParameterValue("InstalledAssemblyTables", "@(InstalledAssemblyTables)", false /* Do not treat as literal */);
            rarTask.SetParameterValue("SearchPaths", "{RawFileName};{TargetFrameworkDirectory};{GAC}");
            rarTask.SetParameterValue("FindDependencies", "true");
            rarTask.SetParameterValue("FindSatellites", "true");
            rarTask.SetParameterValue("FindSerializationAssemblies", "true");
            rarTask.SetParameterValue("FindRelatedFiles", "true");
            rarTask.Condition = String.Format(CultureInfo.InvariantCulture, "Exists('%({0}.Identity)')", referenceItemName);
            rarTask.AddOutputItem("CopyLocalFiles", copyLocalFilesItemName);

            // Copy all the copy-local files (reported by RAR) to the web project's "bin"
            // directory.
            BuildTask copyTask = target.AddNewTask("Copy");
            copyTask.SetParameterValue("SourceFiles", "@(" + copyLocalFilesItemName + ")", false /* DO NOT treat as literal */);
            copyTask.SetParameterValue("DestinationFiles", String.Format(CultureInfo.InvariantCulture,
                @"@({0}->'{1}%(DestinationSubDirectory)%(Filename)%(Extension)')", 
                copyLocalFilesItemName, destinationFolder), false /* DO NOT treat as literal */);
            copyTask.Condition = conditionDescribingValidConfigurations;
        }
Exemplo n.º 20
0
        /// <summary>
        /// Add a target for a project into the XML doc that's being generated.
        /// </summary>
        /// <param name="msbuildProject"></param>
        /// <param name="solution"></param>
        /// <param name="proj"></param>
        /// <param name="targetOutputItemName">The name of the item exposing this target's outputs.  May be null.</param>        
        /// <param name="subTargetName"></param>
        /// <owner>RGoel, LukaszG</owner>
        static private void AddTargetForManagedProject
        (
            Project msbuildProject,
            SolutionParser solution,
            ProjectInSolution proj,
            string targetOutputItemName,
            string subTargetName
        )
        {
            string targetName = ProjectInSolution.DisambiguateProjectTargetName(proj.GetUniqueProjectName());
            if (subTargetName != null && subTargetName.Length > 0)
            {
                targetName = targetName + ":" + subTargetName;
            }

            Target newTarget = msbuildProject.Targets.AddNewTarget(targetName);
            newTarget.DependsOnTargets = GetProjectDependencies(proj.ParentSolution, proj, subTargetName);
            newTarget.Condition = "'$(CurrentSolutionConfigurationContents)' != ''";

            if (!String.IsNullOrEmpty(targetOutputItemName))
            {
                newTarget.TargetElement.SetAttribute("Outputs", string.Format(CultureInfo.InvariantCulture, "@({0})", targetOutputItemName));
            }
            
            // Only create build items if we're called with the null subtarget. We're getting called
            // a total of four times and only want to create the build items once.
            bool createBuildItems = (subTargetName == null);

            foreach (ConfigurationInSolution solutionConfiguration in solution.SolutionConfigurations)
            {
                ProjectConfigurationInSolution projectConfiguration = null;
                string condition = GetConditionStringForConfiguration(solutionConfiguration);

                // Create the build item group for this configuration if we haven't already
                if (solutionConfiguration.ProjectBuildItems == null)
                {
                    solutionConfiguration.ProjectBuildItems = msbuildProject.AddNewItemGroup();
                    solutionConfiguration.ProjectBuildItems.Condition = condition;
                }

                if (proj.ProjectConfigurations.TryGetValue(solutionConfiguration.FullName, out projectConfiguration))
                {
                    if (projectConfiguration.IncludeInBuild)
                    {
                        // We want to specify ToolsVersion on the MSBuild task only if the solution
                        // is building with a non-Whidbey toolset, because the Whidbey MSBuild task
                        // does not support the ToolsVersion parameter.  If the user explicitly requested
                        // the 2.0 toolset be used to build the solution while specifying some value
                        // for the ProjectToolsVersion property, then one of the InitialTargets should
                        // have produced an error before reaching this point.
                        // PERF: We could emit two <MSBuild> tasks, with a condition on them. But this doubles the size of
                        // the solution wrapper project, and the cost is too high. The consequence is that when solution wrapper
                        // projects are emitted to disk (with MSBUILDEMITSOLUION=1) they cannot be reused for tools version v2.0.
                        bool specifyProjectToolsVersion = 
                            String.Equals(msbuildProject.ToolsVersion, "2.0", StringComparison.OrdinalIgnoreCase) ? false : true;

                        BuildTask msbuildTask = AddMSBuildTaskElement(newTarget, proj.RelativePath, subTargetName,
                            projectConfiguration.ConfigurationName, projectConfiguration.PlatformName, specifyProjectToolsVersion);
                        msbuildTask.Condition = condition;

                        if (!String.IsNullOrEmpty(targetOutputItemName))
                        {
                            msbuildTask.AddOutputItem("TargetOutputs", targetOutputItemName);
                        }

                        if (createBuildItems)
                        {
                            string baseItemName = "BuildLevel" + proj.DependencyLevel;
                            BuildItem projectItem = solutionConfiguration.ProjectBuildItems.AddNewItem(baseItemName, proj.RelativePath, true /* treat as literal */);

                            projectItem.SetMetadata("Configuration", EscapingUtilities.Escape(projectConfiguration.ConfigurationName));
                            projectItem.SetMetadata("Platform", EscapingUtilities.Escape(projectConfiguration.PlatformName));
                        }
                    }
                    else
                    {
                        BuildTask messageTask = AddErrorWarningMessageElement(newTarget, XMakeElements.message, true, "SolutionProjectSkippedForBuilding", proj.ProjectName, solutionConfiguration.FullName);
                        messageTask.Condition = condition;

                        if (createBuildItems)
                        {
                            string baseItemName = "SkipLevel" + proj.DependencyLevel;
                            BuildItem projectItem = solutionConfiguration.ProjectBuildItems.AddNewItem(baseItemName, proj.ProjectName, true /* treat as literal */);
                        }
                    }
                }
                else
                {
                    BuildTask warningTask = AddErrorWarningMessageElement(newTarget, XMakeElements.warning, true, "SolutionProjectConfigurationMissing", proj.ProjectName, solutionConfiguration.FullName);
                    warningTask.Condition = condition;

                    if (createBuildItems)
                    {
                        string baseItemName = "MissingConfigLevel" + proj.DependencyLevel;
                        BuildItem projectItem = solutionConfiguration.ProjectBuildItems.AddNewItem(baseItemName, proj.ProjectName, true /* treat as literal */);
                    }
                }
            }
        }
Exemplo n.º 21
0
        /// <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>
        /// <param name="msbuildProject"></param>
        /// <param name="proj"></param>
        /// <param name="configurationName"></param>
        /// <param name="aspNetCompilerParameters"></param>
        /// <param name="solutionFile"></param>
        /// <owner>RGoel</owner>
        static private void AddPropertyGroupForAspNetConfiguration
            (
            Project msbuildProject, 
            ProjectInSolution proj, 
            string configurationName, 
            AspNetCompilerParameters aspNetCompilerParameters,
            string solutionFile
            )
        {
            // Add a new PropertyGroup that is condition'd on the Configuration.
            BuildPropertyGroup newPropertyGroup = msbuildProject.AddNewPropertyGroup(false /* insertAtEndOfProject = false */);
            newPropertyGroup.Condition = String.Format(CultureInfo.InvariantCulture, " '$(AspNetConfiguration)' == '{0}' ", 
                EscapingUtilities.Escape(configurationName));

            // Add properties into the property group for each of the AspNetCompiler properties.
            newPropertyGroup.AddNewProperty(GenerateSafePropertyName(proj, "AspNetVirtualPath"), aspNetCompilerParameters.aspNetVirtualPath, true);
            newPropertyGroup.AddNewProperty(GenerateSafePropertyName(proj, "AspNetPhysicalPath"), aspNetCompilerParameters.aspNetPhysicalPath, true);
            newPropertyGroup.AddNewProperty(GenerateSafePropertyName(proj, "AspNetTargetPath"), aspNetCompilerParameters.aspNetTargetPath, true);
            newPropertyGroup.AddNewProperty(GenerateSafePropertyName(proj, "AspNetForce"), aspNetCompilerParameters.aspNetForce, true);
            newPropertyGroup.AddNewProperty(GenerateSafePropertyName(proj, "AspNetUpdateable"), aspNetCompilerParameters.aspNetUpdateable, true);
            newPropertyGroup.AddNewProperty(GenerateSafePropertyName(proj, "AspNetDebug"), aspNetCompilerParameters.aspNetDebug, true);
            newPropertyGroup.AddNewProperty(GenerateSafePropertyName(proj, "AspNetKeyFile"), aspNetCompilerParameters.aspNetKeyFile, true);
            newPropertyGroup.AddNewProperty(GenerateSafePropertyName(proj, "AspNetKeyContainer"), aspNetCompilerParameters.aspNetKeyContainer, true);
            newPropertyGroup.AddNewProperty(GenerateSafePropertyName(proj, "AspNetDelaySign"), aspNetCompilerParameters.aspNetDelaySign, true);
            newPropertyGroup.AddNewProperty(GenerateSafePropertyName(proj, "AspNetAPTCA"), aspNetCompilerParameters.aspNetAPTCA, true);
            newPropertyGroup.AddNewProperty(GenerateSafePropertyName(proj, "AspNetFixedNames"), aspNetCompilerParameters.aspNetFixedNames, true);

            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),
                        "SolutionParseInvalidProjectFileName",
                        proj.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).
                    BuildProperty targetPathOverrideProperty = newPropertyGroup.AddNewProperty(GenerateSafePropertyName(proj, "AspNetTargetPath"),
                        @"$(OutDir)" + 
                        EscapingUtilities.Escape(webProjectOverrideFolder) + Path.DirectorySeparatorChar + 
                        EscapingUtilities.Escape(lastFolderInPhysicalPath) + Path.DirectorySeparatorChar);
                    targetPathOverrideProperty.Condition = " '$(OutDir)' != '' ";
                }
            }
        }
Exemplo n.º 22
0
        /// <summary>
        /// Adds tasks that create a temporary VC project file with pre-resolved project references (that is,
        /// replaced with file references)
        /// </summary>
        /// <param name="solution"></param>
        /// <param name="target"></param>
        /// <param name="proj"></param>
        /// <param name="solutionConfiguration"></param>
        /// <param name="subTargetName"></param>
        /// <param name="projectConfigurationName"></param>
        /// <returns>The path to the temporary project file</returns>
        /// <owner>LukaszG</owner>
        static private string AddCreateTemporaryVCProjectTasks
        (
            SolutionParser solution,
            Project msbuildProject,
            Target target,
            ProjectInSolution proj,
            ConfigurationInSolution solutionConfiguration,
            string subTargetName,
            string projectConfigurationName
        )
        {
            StringBuilder referenceItemName = new StringBuilder(GenerateSafePropertyName(proj, "References"));
            if (!string.IsNullOrEmpty(subTargetName))
            {
                referenceItemName.Append('_');
                referenceItemName.Append(subTargetName);
            }

            StringBuilder importLibraryItemName = new StringBuilder(GenerateSafePropertyName(proj, "ImportLibraries"));
            if (!string.IsNullOrEmpty(subTargetName))
            {
                importLibraryItemName.Append('_');
                importLibraryItemName.Append(subTargetName);
            }

            string referenceGuidsToRemove = null;

            AddResolveProjectReferenceTasks(solution, msbuildProject, target, proj, solutionConfiguration,
                referenceItemName.ToString(), importLibraryItemName.ToString(), out referenceGuidsToRemove);

            if (string.IsNullOrEmpty(referenceGuidsToRemove))
                referenceGuidsToRemove = string.Empty;

            string fullProjectPath = null;
            string tmpExtension = null;
            string projectPath = null;

            try
            {
                fullProjectPath = proj.AbsolutePath;
                tmpExtension = string.Format(CultureInfo.InvariantCulture, ".tmp_{0}_{1}.vcproj", solutionConfiguration.ConfigurationName, solutionConfiguration.PlatformName);
                projectPath = Path.ChangeExtension(fullProjectPath, tmpExtension);
            }
            catch (Exception e)
            {
                if (ExceptionHandling.NotExpectedException(e))
                    throw;

                ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile(false,
                    "SubCategoryForSolutionParsingErrors",
                    new BuildEventFileInfo(solution.SolutionFile),
                    "SolutionParseInvalidProjectFileName",
                    proj.RelativePath, e.Message);
            }


            // Create the temporary VC project
            BuildTask createVCProjectTask = target.AddNewTask("CreateTemporaryVCProject");
            createVCProjectTask.SetParameterValue("ProjectFile", fullProjectPath, true /* treat as literal */);
            createVCProjectTask.SetParameterValue("Configuration", projectConfigurationName, true /* treat as literal */);
            createVCProjectTask.SetParameterValue("OutputProjectFile", projectPath, true /* treat as literal */);

            createVCProjectTask.SetParameterValue("ReferenceGuids", referenceGuidsToRemove, false /* Contains semicolon-separated list.  DO NOT treat as literal */);
            createVCProjectTask.SetParameterValue("ReferenceAssemblies",
                string.Format(CultureInfo.InvariantCulture, "@({0})", referenceItemName.ToString()), false /* DO NOT treat as literal */);
            createVCProjectTask.SetParameterValue("ReferenceImportLibraries",
                string.Format(CultureInfo.InvariantCulture, "@({0})", importLibraryItemName.ToString()), false /* DO NOT treat as literal */);

            createVCProjectTask.Condition = GetConditionStringForConfiguration(solutionConfiguration);

            return projectPath;
        }
Exemplo n.º 23
0
        /// <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>
        /// <param name="target"></param>
        /// <param name="proj"></param>
        /// <param name="referenceItemName"></param>
        /// <owner>RGoel</owner>
        static private void AddTasksToResolveAutoRefreshFileReferences
            (
            Target target, 
            ProjectInSolution proj, 
            string referenceItemName
            )
        {
            string webRoot = "$(" + GenerateSafePropertyName(proj, "AspNetPhysicalPath") + ")";

            // Create an item list containing each of the .REFRESH files.
            BuildTask createItemTask = target.AddNewTask("CreateItem");
            createItemTask.SetParameterValue("Include", webRoot + @"\Bin\*.refresh");
            createItemTask.AddOutputItem("Include", referenceItemName + "_RefreshFile");

            // Read the lines out of each .REFRESH file; they should be paths to .DLLs.  Put these paths
            // into an item list.
            BuildTask readLinesTask = target.AddNewTask("ReadLinesFromFile");
            readLinesTask.SetParameterValue("File", 
                String.Format(CultureInfo.InvariantCulture, @"%({0}_RefreshFile.Identity)", referenceItemName));
            readLinesTask.Condition = String.Format(CultureInfo.InvariantCulture, @" '%({0}_RefreshFile.Identity)' != '' ", referenceItemName);
            readLinesTask.AddOutputItem("Lines", referenceItemName + "_ReferenceRelPath");

            // 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.
            BuildTask combinePathTask = target.AddNewTask("CombinePath");
            combinePathTask.SetParameterValue("BasePath", webRoot);
            combinePathTask.SetParameterValue("Paths", 
                String.Format(CultureInfo.InvariantCulture, @"@({0}_ReferenceRelPath)", referenceItemName));
            combinePathTask.AddOutputItem("CombinedPaths", referenceItemName);
        }
Exemplo n.º 24
0
        /// <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>
        /// <param name="solution"></param>
        /// <param name="proj"></param>
        /// <returns></returns>
        /// <owner>RGoel</owner>
        static private string ComputeTargetConditionForWebProject
            (
            SolutionParser solution,
            ProjectInSolution proj
            )
        {
            StringBuilder condition = new StringBuilder(" ('$(CurrentSolutionConfigurationContents)' != '') and (false");

            // Loop through all the solution configurations.
            foreach (ConfigurationInSolution solutionConfiguration in solution.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 (proj.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();
        }
Exemplo n.º 25
0
        public void ParseFirstProjectLineWhereProjectNameHasSpecialCharacters()
        {
            SolutionParser p = new SolutionParser();
            p.SolutionFile = "foobar.sln";
            ProjectInSolution proj = new ProjectInSolution(p);

            p.ParseFirstProjectLine
            (
                "Project(\"{Project GUID}\")  = \"MyProject,(=IsGreat)\",  \"Relative path to project file\"    , \"Unique name-GUID\"", 
                 proj
            );
            Assertion.AssertEquals(SolutionProjectType.Unknown, proj.ProjectType);
            Assertion.AssertEquals("MyProject,(=IsGreat)", proj.ProjectName);
            Assertion.AssertEquals("Relative path to project file", proj.RelativePath);
            Assertion.AssertEquals("Unique name-GUID", proj.ProjectGuid);
        }