/// <summary> /// Checks if the project build is up to date. /// </summary> public async Task <bool> ProjectIsUpToDateAsync(SolutionItem project) { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IVsSolutionBuildManager svc = await VS.Services.GetSolutionBuildManagerAsync(); IVsProjectCfg2[] projectConfig = new IVsProjectCfg2[1]; project.GetItemInfo(out IVsHierarchy hierarchy, out _, out _); if (ErrorHandler.Succeeded(svc.FindActiveProjectCfg(IntPtr.Zero, IntPtr.Zero, hierarchy, projectConfig))) { int[] supported = new int[1]; int[] ready = new int[1]; if (ErrorHandler.Succeeded(projectConfig[0].get_BuildableProjectCfg(out IVsBuildableProjectCfg buildableProjectConfig)) && ErrorHandler.Succeeded(buildableProjectConfig.QueryStartUpToDateCheck(0, supported, ready)) && supported[0] == 1) { return(ErrorHandler.Succeeded(buildableProjectConfig.StartUpToDateCheck(null, (uint)VsUpToDateCheckFlags.VSUTDCF_DTEEONLY))); } } return(false); }
//Code from StaticAnalysisPolicy class in the StanPolicy.dll file private bool ProjectUptoDate(Project project, List <PolicyFailure> failuresList) { IVsBuildableProjectCfg cfg1; IVsHierarchy hierarchy1 = GetVsProjectFromDTE(project); IVsProjectCfg2[] cfgArray1 = new IVsProjectCfg2[1]; IVsSolutionBuildManager m_currBuildManager = PendingCheckin.GetService(typeof(IVsSolutionBuildManager)) as IVsSolutionBuildManager; m_currBuildManager.FindActiveProjectCfg(IntPtr.Zero, IntPtr.Zero, hierarchy1, cfgArray1); if (cfgArray1[0] == null) { return(false); } cfgArray1[0].get_BuildableProjectCfg(out cfg1); if (cfg1 == null) { return(false); } int[] numArray1 = new int[1]; int[] numArray2 = new int[1]; int num1 = cfg1.QueryStartUpToDateCheck(1, numArray1, numArray2); if ((numArray1[0] != 0) && !ErrorHandler.Failed(num1)) { //http://msdn2.microsoft.com/en-us/library/microsoft.visualstudio.shell.interop.ivsbuildableprojectcfg.startuptodatecheck(VS.80).aspx num1 = cfg1.StartUpToDateCheck(null, 1); if (ErrorHandler.Failed(num1)) { string text1 = String.Format(errMessage, project.Name); failuresList.Add(new PolicyFailure(text1, this)); return(false); } } return(true); }
/// <summary> /// When building a wixproj in VS, the configuration of referenced projects cannot be determined /// by MSBuild or from within an MSBuild task. So we'll get them from the VS project system here. /// </summary> /// <param name="project">The project where the properties are being defined; also the project /// whose references are being examined.</param> internal static void DefineProjectReferenceConfigurations(WixProjectNode project) { StringBuilder configList = new StringBuilder(); IVsSolutionBuildManager solutionBuildManager = WixHelperMethods.GetService <IVsSolutionBuildManager, SVsSolutionBuildManager>(project.Site); List <WixProjectReferenceNode> referenceNodes = new List <WixProjectReferenceNode>(); project.FindNodesOfType(referenceNodes); foreach (WixProjectReferenceNode referenceNode in referenceNodes) { IVsHierarchy hierarchy = VsShellUtilities.GetHierarchy(referenceNode.ProjectMgr.Site, referenceNode.ReferencedProjectGuid); string configuration = null; IVsProjectCfg2 projectCfg2 = null; IVsProjectCfg[] projectCfgArray = new IVsProjectCfg[1]; int hr = solutionBuildManager.FindActiveProjectCfg(IntPtr.Zero, IntPtr.Zero, hierarchy, projectCfgArray); ErrorHandler.ThrowOnFailure(hr); projectCfg2 = projectCfgArray[0] as IVsProjectCfg2; if (projectCfg2 != null) { hr = projectCfg2.get_DisplayName(out configuration); if (hr != 0) { Marshal.ThrowExceptionForHR(hr); } } if (configuration != null) { if (configList.Length > 0) { configList.Append(';'); } configList.Append(referenceNode.ReferencedProjectName); configList.Append('='); configList.Append(configuration); } } if (configList.Length > 0) { project.BuildProject.SetGlobalProperty("VSProjectConfigurations", configList.ToString()); } }
/// <summary> /// When building a project in VS, the configuration of referenced projects cannot be determined /// by MSBuild or from within an MSBuild task. So we'll get them from the VS project system here. /// </summary> /// <param name="project">The project where the properties are being defined; also the project /// whose references are being examined.</param> internal static void DefineProjectReferenceConfigurations(XProjectNode project) { StringBuilder configList = new StringBuilder(); IVsSolutionBuildManager solutionBuildManager = XHelperMethods.GetService <IVsSolutionBuildManager, SVsSolutionBuildManager>(project.Site); List <ProjectReferenceNode> referenceNodes = new List <ProjectReferenceNode>(); project.FindNodesOfType(referenceNodes); foreach (ProjectReferenceNode referenceNode in referenceNodes) { try { IVsHierarchy hierarchy = VsShellUtilities.GetHierarchy(referenceNode.ProjectMgr.Site, referenceNode.ReferencedProjectGuid); string configuration = null; IVsProjectCfg2 projectCfg2 = null; IVsProjectCfg[] projectCfgArray = new IVsProjectCfg[1]; ThreadHelper.ThrowIfNotOnUIThread(); // this can fail for some reason... this code was copied from Wix and probably isn't stable yet. // this routine is called from InvokeMSBuild and we don't want that to fix because of // some bug here, so this code is surrounded by try/catch until we figure this out int hr = solutionBuildManager.FindActiveProjectCfg(IntPtr.Zero, IntPtr.Zero, hierarchy, projectCfgArray); ErrorHandler.ThrowOnFailure(hr); projectCfg2 = projectCfgArray[0] as IVsProjectCfg2; if (projectCfg2 != null) { hr = projectCfg2.get_DisplayName(out configuration); if (hr != 0) { Marshal.ThrowExceptionForHR(hr); } } if (configuration != null) { if (configList.Length > 0) { configList.Append(';'); } configList.Append(referenceNode.ReferencedProjectName); configList.Append('='); configList.Append(configuration); } } catch (Exception) { ; } } if (configList.Length > 0) { project.BuildProject.SetGlobalProperty("VSProjectConfigurations", configList.ToString()); } }
/// <summary> /// Gets the variables and directories for the specified project. Variables will be in /// the form <c>ProjectName.VariableName</c>. /// </summary> /// <param name="variables">The <see cref="NameValueCollection"/> to add the variables to.</param> /// <param name="hierarchy">The <see cref="IVsHierarchy"/> (project) from which to retrieve the variables.</param> private void GetTargetVariables(NameValueCollection variables, IVsHierarchy hierarchy, string projectPrefix) { try { int hr = NativeMethods.S_OK; // Now we need to get a IVsProjectCfg2 object to get the TargetX variables. We do this // by querying the environment for the active configuration of the specified project. IVsSolutionBuildManager solutionBuildManager = Package.Instance.GetService(typeof(IVsSolutionBuildManager)) as IVsSolutionBuildManager; if (solutionBuildManager == null) { Tracer.WriteLine(classType, "GetTargetVariables", Tracer.Level.Warning, "Cannot get an instance of IVsSolutionBuildManager from the environment. Skipping the project's TargetX variables."); return; } IVsProjectCfg[] projectCfgArray = new IVsProjectCfg[1]; hr = solutionBuildManager.FindActiveProjectCfg(IntPtr.Zero, IntPtr.Zero, hierarchy, projectCfgArray); if (NativeMethods.Failed(hr)) { Tracer.WriteLineWarning(classType, "GetTargetVariables", "One of the projects in the solution does not support project configurations. Skipping the project's TargetX variables."); return; } IVsProjectCfg2 projectCfg2 = projectCfgArray[0] as IVsProjectCfg2; if (projectCfg2 == null) { Tracer.WriteLine(classType, "GetTargetVariables", Tracer.Level.Warning, "The IVsSolutionBuildManager.FindActiveProjectCfg returned a null object or an object that doesn't support IVsProjectCfg2. Skipping the project's TargetX variables."); return; } // Get the ConfigurationName and add it to the variables. string configurationName; NativeMethods.ThrowOnFailure(projectCfg2.get_DisplayName(out configurationName)); variables.Add(projectPrefix + "ConfigurationName", configurationName); // We need to get the Built output group from the list of project output groups. IVsOutputGroup outputGroup; NativeMethods.ThrowOnFailure(projectCfg2.OpenOutputGroup("Built", out outputGroup)); if (outputGroup == null) { Tracer.WriteLine(classType, "GetTargetVariables", Tracer.Level.Warning, "The project configuration '{0}' does not support the 'Built' output group. Skipping the TargetX variables.", configurationName); return; } // Get the key output canonical name from the Built output group. string keyOutputCanonicalName; NativeMethods.ThrowOnFailure(outputGroup.get_KeyOutput(out keyOutputCanonicalName)); // Search through the outputs until we find the key output. We have to call get_Outputs // twice: once to get the number of outputs (we do this by passing in 0 as the number // requested), and then once to get the actual outputs. uint numberRequested = 0; IVsOutput2[] outputArray = new IVsOutput2[numberRequested]; uint[] numberFetchedArray = new uint[1]; NativeMethods.ThrowOnFailure(outputGroup.get_Outputs(numberRequested, outputArray, numberFetchedArray)); // We should have the number of elements in the output array now, so get them. numberRequested = numberFetchedArray[0]; outputArray = new IVsOutput2[numberRequested]; NativeMethods.ThrowOnFailure(outputGroup.get_Outputs(numberRequested, outputArray, numberFetchedArray)); IVsOutput2 keyOutput = null; for (int i = 0; i < numberFetchedArray[0]; i++) { if (outputArray.Length <= i) { break; } IVsOutput2 output = outputArray[i]; string outputCanonicalName; NativeMethods.ThrowOnFailure(output.get_CanonicalName(out outputCanonicalName)); if (outputCanonicalName == keyOutputCanonicalName) { keyOutput = output; break; } } // Check to make sure that we found the key output. if (keyOutput == null) { Tracer.WriteLine(classType, "GetTargetVariables", Tracer.Level.Warning, "We identified the key output from configuration '{0}' as '{1}', but when we iterated through the outputs we couldn't find the key output. Skipping the TargetX variables.", configurationName, keyOutputCanonicalName); return; } // Now that we have the key output, we can finally create the TargetX variables from // the key output's deploy source URL. string deploySourceUrl; NativeMethods.ThrowOnFailure(keyOutput.get_DeploySourceURL(out deploySourceUrl)); // By convention, the deploy source URL starts with file:/// for file-based outputs. // Strip it off if it's there. if (deploySourceUrl.StartsWith("file:///")) { deploySourceUrl = deploySourceUrl.Substring("file:///".Length); } // Parse the TargetX variables from the deploy source URL. string targetPath = deploySourceUrl; string targetFileName = Path.GetFileName(targetPath); string targetDosFileName = this.EncodeDosFileName(targetFileName); string targetName = Path.GetFileNameWithoutExtension(targetFileName); string targetExt = PackageUtility.EnsureLeadingChar(Path.GetExtension(targetPath), '.'); string targetDir = PackageUtility.StripTrailingChar(Path.GetDirectoryName(targetPath), Path.DirectorySeparatorChar); // Add the TargetX variables to the collection. variables.Add(projectPrefix + "TargetDir", targetDir); variables.Add(projectPrefix + "TargetDosFileName", targetDosFileName); variables.Add(projectPrefix + "TargetExt", targetExt); variables.Add(projectPrefix + "TargetFileName", targetFileName); variables.Add(projectPrefix + "TargetName", targetName); variables.Add(projectPrefix + "TargetPath", targetPath); } catch (Exception e) { if (ErrorUtility.IsExceptionUnrecoverable(e)) { throw; } Tracer.WriteLineWarning(classType, "GetTargetVariables", "The project does not correctly implement all of its required IVsProjectCfg2 interfaces. Skipping the TargetX variables. Exception: {0}", e); } }