/// <summary>
        /// Add a PropertyGroup to the project for a particular Asp.Net configuration.  This PropertyGroup
        /// will have the correct values for all the Asp.Net properties for this project and this configuration.
        /// </summary>
        private void AddPropertyGroupForAspNetConfiguration
            (
            ProjectInstance traversalProject,
            ProjectInstance metaprojectInstance,
            ProjectInSolution project,
            string configurationName,
            AspNetCompilerParameters aspNetCompilerParameters,
            string solutionFile
            )
        {
            // If the configuration doesn't match, don't add the properties.
            if (!traversalProject.EvaluateCondition(String.Format(CultureInfo.InvariantCulture, " '$(AspNetConfiguration)' == '{0}' ", EscapingUtilities.Escape(configurationName))))
            {
                return;
            }

            // Add properties into the property group for each of the AspNetCompiler properties.
            // REVIEW: SetProperty takes an evaluated value.  Are we doing the right thing here?
            metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetVirtualPath"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetVirtualPath));
            metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetPhysicalPath"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetPhysicalPath));
            metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetTargetPath"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetTargetPath));
            metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetForce"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetForce));
            metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetUpdateable"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetUpdateable));
            metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetDebug"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetDebug));
            metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetKeyFile"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetKeyFile));
            metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetKeyContainer"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetKeyContainer));
            metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetDelaySign"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetDelaySign));
            metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetAPTCA"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetAPTCA));
            metaprojectInstance.SetProperty(GenerateSafePropertyName(project, "AspNetFixedNames"), EscapingUtilities.Escape(aspNetCompilerParameters.aspNetFixedNames));

            string aspNetPhysicalPath = aspNetCompilerParameters.aspNetPhysicalPath;
            if (!String.IsNullOrEmpty(aspNetPhysicalPath))
            {
                // Trim the trailing slash if one exists.
                if (
                        (aspNetPhysicalPath[aspNetPhysicalPath.Length - 1] == Path.AltDirectorySeparatorChar) ||
                        (aspNetPhysicalPath[aspNetPhysicalPath.Length - 1] == Path.DirectorySeparatorChar)
                    )
                {
                    aspNetPhysicalPath = aspNetPhysicalPath.Substring(0, aspNetPhysicalPath.Length - 1);
                }

                // This gets us the last folder in the physical path.
                string lastFolderInPhysicalPath = null;

                try
                {
                    lastFolderInPhysicalPath = Path.GetFileName(aspNetPhysicalPath);
                }
                catch (Exception e)
                {
                    if (ExceptionHandling.NotExpectedException(e))
                    {
                        throw;
                    }

                    ProjectFileErrorUtilities.VerifyThrowInvalidProjectFile
                        (
                        false,
                        "SubCategoryForSolutionParsingErrors",
                        new BuildEventFileInfo(solutionFile),
                        e,
                        "SolutionParseInvalidProjectFileName",
                        project.RelativePath,
                        e.Message
                        );
                }

                if (!String.IsNullOrEmpty(lastFolderInPhysicalPath))
                {
                    // If there is a global property called "OutDir" set, that means the caller is trying to 
                    // override the AspNetTargetPath.  What we want to do in this case is concatenate:
                    // $(OutDir) + "\_PublishedWebsites" + (the last portion of the folder in the AspNetPhysicalPath).
                    if (traversalProject.EvaluateCondition(" '$(OutDir)' != '' "))
                    {
                        string outDirValue = String.Empty;
                        ProjectPropertyInstance outdir = metaprojectInstance.GetProperty("OutDir");

                        if (outdir != null)
                        {
                            outDirValue = ProjectInstance.GetPropertyValueEscaped(outdir);
                        }

                        // Make sure the path we are appending to has no leading slash to prevent double slashes.
                        string publishWebsitePath = EscapingUtilities.Escape(WebProjectOverrideFolder) + Path.DirectorySeparatorChar + EscapingUtilities.Escape(lastFolderInPhysicalPath) + Path.DirectorySeparatorChar;

                        metaprojectInstance.SetProperty
                            (
                            GenerateSafePropertyName(project, "AspNetTargetPath"),
                            outDirValue + publishWebsitePath
                            );
                    }
                }
            }
        }
Example #2
0
        /// <summary>
        /// Start MSBuild build submission
        /// </summary>
        /// If buildKind is ASYNC, this method starts the submission ane returns. uiThreadCallback will be called on UI thread once submissions completes.
        /// if buildKind is SYNC, this method executes the submission and runs uiThreadCallback
        /// <param name="buildKind">Is it a SYNC or ASYNC build</param>
        /// <param name="target">target to build</param>
        /// <param name="projectInstance">project instance to build; if null, this.BuildProject.CreateProjectInstance() is used to populate</param>
        /// <param name="uiThreadCallback">callback to be run UI thread </param>
        /// <returns></returns>
        internal virtual BuildSubmission DoMSBuildSubmission(BuildKind buildKind, string target, ref ProjectInstance projectInstance, MSBuildCoda uiThreadCallback)
        {
            UIThread.MustBeCalledFromUIThread();
            bool designTime = BuildKind.SYNC == buildKind;
            //projectInstance = null;

            var accessor = (IVsBuildManagerAccessor)this.Site.GetService(typeof(SVsBuildManagerAccessor));
            if (!TryBeginBuild(designTime))
            {
                if (null != uiThreadCallback)
                {
                    uiThreadCallback(MSBuildResult.Failed, projectInstance);
                }

                return null;
            }

            string[] targetsToBuild = new string[target != null ? 1 : 0];
            if (target != null)
            {
                targetsToBuild[0] = target;
            }

            if (null == projectInstance)
            {
                projectInstance = BuildProject.CreateProjectInstance();
            }

            projectInstance.SetProperty(GlobalProperty.VisualStudioStyleErrors.ToString(), "true");
            projectInstance.SetProperty("UTFOutput", "true");
            projectInstance.SetProperty(GlobalProperty.BuildingInsideVisualStudio.ToString(), "true");

            this.BuildProject.ProjectCollection.HostServices.SetNodeAffinity(projectInstance.FullPath, NodeAffinity.InProc);
            BuildRequestData requestData = new BuildRequestData(projectInstance, targetsToBuild, this.BuildProject.ProjectCollection.HostServices, BuildRequestDataFlags.ReplaceExistingProjectInstance);
            BuildSubmission submission = BuildManager.DefaultBuildManager.PendBuildRequest(requestData);
            try
            {
                if (useProvidedLogger && buildLogger != null)
                {
                    ErrorHandler.ThrowOnFailure(accessor.RegisterLogger(submission.SubmissionId, buildLogger));
                }

                if (buildKind == BuildKind.ASYNC)
                {
                    ProjectInstance projectInstanceCopy = projectInstance;
                    submission.ExecuteAsync(sub =>
                    {
                        UIThread.Run(() =>
                        {
                            this.FlushBuildLoggerContent();
                            EndBuild(sub, designTime);
                            uiThreadCallback((sub.BuildResult.OverallResult == BuildResultCode.Success) ? MSBuildResult.Successful : MSBuildResult.Failed, projectInstanceCopy);
                        });
                    }, null);
                }
                else
                {
                    submission.Execute();
                    EndBuild(submission, designTime);
                    MSBuildResult msbuildResult = (submission.BuildResult.OverallResult == BuildResultCode.Success) ? MSBuildResult.Successful : MSBuildResult.Failed;
                    if (uiThreadCallback != null)
                    {
                        uiThreadCallback(msbuildResult, projectInstance);
                    }
                }
            }
            catch (Exception e)
            {
                Debug.Fail(e.ToString());
                EndBuild(submission, designTime);
                if (uiThreadCallback != null)
                {
                    uiThreadCallback(MSBuildResult.Failed, projectInstance);
                }

                throw;
            }

            return submission;
        }
Example #3
0
		// To NOT reuse this IBuildEngine instance for different build, we create another BuildManager and BuildSubmisson and then run it.
		public bool BuildProjectFile (string projectFileName, string[] targetNames, IDictionary globalProperties, IDictionary targetOutputs, string toolsVersion)
		{
			toolsVersion = string.IsNullOrEmpty (toolsVersion) ? project.ToolsVersion : toolsVersion;
			var globalPropertiesThatMakeSense = new Dictionary<string,string> ();
			foreach (DictionaryEntry p in globalProperties)
				globalPropertiesThatMakeSense [(string) p.Key] = (string) p.Value;
			var projectToBuild = new ProjectInstance (ProjectRootElement.Create (XmlReader.Create (projectFileName)), globalPropertiesThatMakeSense, toolsVersion, Projects);
			// Not very sure if ALL of these properties should be added, but some are certainly needed. 
			foreach (var p in this.project.Properties.Where (p => !globalProperties.Contains (p.Name)))
				projectToBuild.SetProperty (p.Name, p.EvaluatedValue);
			
			IDictionary<string,TargetResult> outs;
			var ret = projectToBuild.Build (targetNames ?? new string [] {"Build"}, Projects.Loggers, out outs);
			foreach (var p in outs)
				targetOutputs [p.Key] = p.Value.Items ?? new ITaskItem [0];
			return ret;
		}
        /// <summary>
        /// Called before the first project configuration is about to be built.
        /// </summary>
        /// <returns>
        /// If the method succeeds, it returns <see cref="F:Microsoft.VisualStudio.VSConstants.S_OK"/>. If it fails, it returns an error code.
        /// </returns>
        /// <param name="pfCancelUpdate">[in, out] Pointer to a flag indicating cancel update.</param>
        int IVsUpdateSolutionEvents.UpdateSolution_StartUpdate(ref int pfCancelUpdate)
        {
            // This method is called when the entire solution starts to build.
            this.WriteLine(LoggerVerbosity.Detailed, "CommonSolutionTargets: UpdateSolution_StartUpdate");

            string solutionFilePath = this.dte2.Solution.FullName;
            string solutionFolder = Path.GetDirectoryName(solutionFilePath);
            string solutionFileName = Path.GetFileName(solutionFilePath);
            string targetsFileName = "after." + solutionFileName + ".targets";
            if (solutionFolder == null)
                return VSConstants.E_UNEXPECTED;

            string targetsFilePath = Path.Combine(solutionFolder, targetsFileName);

            if (!File.Exists(targetsFilePath))
                return VSConstants.S_OK;

            string solutionConfigurationName = this.dte2.Solution.SolutionBuild.ActiveConfiguration.Name;
            this.WriteLine(LoggerVerbosity.Detailed, "CommonSolutionTargets: active solution configuration name is \"{0}\"", solutionConfigurationName);

            List<ILogger> loggers = new List<ILogger> { this.MakeBuildLogger() };

            ProjectInstance solutionInitProjectInstance;
            try
            {
                solutionInitProjectInstance = new ProjectInstance(targetsFilePath);
            }
            catch (Exception ex)
            {
                this.WriteLine(LoggerVerbosity.Detailed, "CommonSolutionTargets: failed to load targets file \"{0}\", Exception: {1}", targetsFilePath, ex);
                return VSConstants.E_FAIL;
            }
            solutionInitProjectInstance.SetProperty("Configuration", solutionConfigurationName);
            solutionInitProjectInstance.SetProperty("BuildingInsideVisualStudio", "true");
            int numberOfPropertiesBeforeBuild = solutionInitProjectInstance.Properties.Count;
            this.WriteLine(LoggerVerbosity.Detailed, "CommonSolutionTargets: building targets file \"{0}\", target \"{1}\"", targetsFilePath, this.activeBuildTarget);
            solutionInitProjectInstance.Build(this.activeBuildTarget, loggers);

            // If solution targets build produced new custom properties, fetch those and add them to the global properties collection.
            // Most typical usage for this feature is setting "CustomAfterMicrosoftCommontargets" property.
            for (int propertyNumber = numberOfPropertiesBeforeBuild;
                propertyNumber < solutionInitProjectInstance.Properties.Count;
                propertyNumber++)
            {
                ProjectPropertyInstance property = solutionInitProjectInstance.Properties.ElementAt(propertyNumber);
                if (property.Name.StartsWith("Custom"))
                {
                    this.WriteLine(LoggerVerbosity.Detailed, "CommonSolutionTargets: defined global build property {0} = {1}", property.Name, property.EvaluatedValue);
                    ProjectCollection.GlobalProjectCollection.SetGlobalProperty(property.Name, property.EvaluatedValue);
                }
            }

            return VSConstants.S_OK;
        }