Exemplo n.º 1
0
        /// <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);
            }
        }
Exemplo n.º 2
0
        /// <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 GetProjectVariables(NameValueCollection variables, IVsHierarchy hierarchy)
        {
            // ProjectX variables
            try
            {
                int hr = NativeMethods.S_OK;

                // Get the project name and directory from the hierarchy.
                object projectNameObj;
                object projectDirObj;
                hr = hierarchy.GetProperty(NativeMethods.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ProjectName, out projectNameObj);
                hr = hierarchy.GetProperty(NativeMethods.VSITEMID_ROOT, (int)__VSHPROPID.VSHPROPID_ProjectDir, out projectDirObj);

                // To get the project file path, we have to get an IPersistFileFormat interface from the hierarchy.
                IPersistFileFormat persistFileFormat = hierarchy as IPersistFileFormat;

                // Sometimes the hierarchy doesn't always support all of these requested properties.
                // We have to have all three to properly get all of the project properties.
                if (projectNameObj == null || projectDirObj == null || persistFileFormat == null)
                {
                    Tracer.WriteLine(classType, "GetProjectVariables", Tracer.Level.Warning, "The hierarchy '{0}' does not support one of the VSHPROPID_ProjectName, VSHPROPID_ProjectDir, or IPersistFileFormat properties. Skipping the project variables.", projectNameObj);
                    return;
                }

                // Get the project path.
                string projectPath;
                uint   formatIndex;
                NativeMethods.ThrowOnFailure(persistFileFormat.GetCurFile(out projectPath, out formatIndex));

                // Construct the ProjectX variables from the ones retrieved from the hierarchy.
                string projectName        = (string)projectNameObj;
                string projectDir         = PackageUtility.StripTrailingChar((string)projectDirObj, Path.DirectorySeparatorChar);
                string projectFileName    = Path.GetFileName(projectPath);
                string projectExt         = PackageUtility.EnsureLeadingChar(Path.GetExtension(projectPath), '.');
                string projectDosFileName = this.EncodeDosFileName(projectFileName);

                // The variable name will be in the form ProjectName.VariableName. We have to strip out
                // any illegal characters from the project name since this will be a preprocessor definition.
                string projectPrefix = this.EncodeProjectName(projectName) + ".";

                // Add the ProjectX variables to the collection.
                variables.Add(projectPrefix + "ProjectDir", projectDir);
                variables.Add(projectPrefix + "ProjectDosFileName", projectDosFileName);
                variables.Add(projectPrefix + "ProjectExt", projectExt);
                variables.Add(projectPrefix + "ProjectFileName", projectFileName);
                variables.Add(projectPrefix + "ProjectName", projectName);
                variables.Add(projectPrefix + "ProjectPath", projectPath);

                // TargetX variables
                this.GetTargetVariables(variables, hierarchy, projectPrefix);
            }
            catch (Exception e)
            {
                if (ErrorUtility.IsExceptionUnrecoverable(e))
                {
                    throw;
                }

                Tracer.WriteLineWarning(classType, "GetProjectVariables", "There was an error while trying to get the project variables. Skipping the ProjectX variables. Exception: {0}", e);
            }
        }