如何考虑解决方案文件夹以编程方式迭代Visual Studio 2008解决方案的所有项目

时间:2016-01-26 10:53:50

标签: visual-studio-2008 envdte vcproj

我正在尝试以编程方式浏览Visual Studio 2008解决方案的所有项目,以确保某些项目设置的正确值。

我正在尝试使用VBS和DTE,但我并不坚持使用特定的语言/ API /框架,除了我不想在XML级别调整项目设置。

以下VBS代码的问题在于它没有遇到任何项目(因为它们都包含在解决方案文件夹中) - 相反,我只是获得了解决方案文件夹的列表。

示例msgbox输出:

NAME:Gateways TYPE: {66A26720-8FB5-11D2-AA7E-00C04F688DDE}

上述GUID对于所有解决方案文件夹实际上都是相同的。

solutionfile = CreateObject("Scripting.FileSystemObject").GetParentFolderName(WScript.ScriptFullName) + "\big_solution.sln"
msgbox(solutionfile)
Set dte = CreateObject("VisualStudio.DTE.9.0")
dte.MainWindow.Visible = True

Call dte.solution.open(solutionfile)
Set prjs = DTE.Solution.Projects
For i = 1 To prjs.Count
    Set p = prjs.Item(i)
    msgbox("NAME:" & p.Name & " TYPE: " & p.Kind & vbCr)
Next

Call dte.solution.SaveAs(dte.solution.FileName)
dte.solution.close

msgbox solutionfile + " successfully updated."

dte.UserControl = True

感谢任何提示!

1 个答案:

答案 0 :(得分:1)

要使用VS2008解决方案,首先需要

  

c:\ Program Files(x86)\ Microsoft Visual Studio 9.0 \ Common7 \ IDE \ PublicAssemblies \ EnvDTE.dll

但它不公开所有类型项目的所有属性(例如,属性" InheritedPropertySheets"在C ++项目中不可访问)。要正确访问C ++项目,您还需要:

  

c:\ Program Files(x86)\ Microsoft Visual Studio 9.0 \ Common7 \ IDE \ PublicAssemblies \ Microsoft.VisualStudio.VCProjectEngine.dll

遍历解决方案的C#(.NET 3.5)示例,确保每个C ++项目继承我们的自定义Property Sheet,然后在Post-Build Step中使用宏" THETARGETDIR"这是在我们的物业单中集中定义的。

using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using EnvDTE;
using Microsoft.VisualStudio.VCProjectEngine;

namespace FixSolution
{
    class Program
    {
        private class Stats
        {
            public int n_pbs_adjusted = 0;
            public int n_projects = 0;
            public int n_projects_cpp = 0;
            public int n_ps_adjusted = 0;
            public int n_consistency_errors = 0;
        }
        private static Stats _stats = new Stats();

        static void ProcessSolutionFolder(Project p)
        {
            foreach (ProjectItem pi in p.ProjectItems)
            {
                Project pp = pi.Object as Project;
                if (pp == null)
                {
                    continue; // solution item but not a project (e.g. big_solution_explained.txt)
                }

                if (pp.Kind == FixSolution.Properties.Settings.Default.SF_GUID)
                    ProcessSolutionFolder(pp);
                else
                    ProcessProject(pp);
            }
        }

        private static int NextHardcoded(string cmd)
        {
            return cmd.ToLower().IndexOf(FixSolution.Properties.Settings.Default.STD_TARGET);
        }

        private static bool ProcessVCPostBuildEventTool(VCConfiguration c)
        {
            IVCCollection cc = c.Tools as IVCCollection;
            if (cc == null) return false;
            bool adjusted = false;
            foreach (Object tool in cc)
            {
                VCPostBuildEventTool pbs = tool as VCPostBuildEventTool;
                if (pbs == null || pbs.CommandLine == null) continue;

                int pos = NextHardcoded(pbs.CommandLine);
                var before_adjustment = pbs.CommandLine;
                while (pos != -1)
                {
                    adjusted = true;
                    string CMD = pbs.CommandLine;
                    int tl = FixSolution.Properties.Settings.Default.STD_TARGET.Length;
                    pbs.CommandLine = CMD.Substring(0, pos) + "$(THETARGETDIR)" + CMD.Substring(pos + tl, CMD.Length - pos - tl);

                    pos = NextHardcoded(pbs.CommandLine);
                }

                if (adjusted)
                {
                    VCProject p = c.project as VCProject;
                    Console.WriteLine("\nWARNING: project " + p.ProjectFile
                        + "\nConfiguration " + c.ConfigurationName + " contains hardcoded sophis directory in PBS:"
                        + "\n" + before_adjustment);
                    Console.WriteLine("REPLACED BY:");
                    Console.WriteLine(pbs.CommandLine);
                }
            }
            return adjusted;
        }

        private static void ProcessProject(Project pp)
        {
            ++_stats.n_projects;
            VCProject p = pp.Object as VCProject;
            if (p == null)
                return; // not a C++ project

            ++_stats.n_projects_cpp;
            string vsprops_path = Util.GetRelativePath(p.ProjectDirectory, FixSolution.Properties.Settings.Default.AbsoluteVspropsPath);

            bool adjusted_ps = false;
            bool adjusted_pbs = false;

            foreach (VCConfiguration c in (IVCCollection)p.Configurations)
            {
                if (ProcessVCPostBuildEventTool(c))
                    adjusted_pbs = true;

                if (c.InheritedPropertySheets == vsprops_path)
                {
                    continue;
                }
                if (c.InheritedPropertySheets.Length > 0)
                {
                    Console.WriteLine("WARNING: project " + pp.FullName + " config " + c.Name + " has unusual InheritedPropertySheets: " + c.InheritedPropertySheets);
                    ++_stats.n_consistency_errors; // counting the unexpected, per configuration
                }
                adjusted_ps = true;
                c.InheritedPropertySheets = vsprops_path;
            }

            if (adjusted_ps)
                ++_stats.n_ps_adjusted; 
            if (adjusted_pbs)
                ++_stats.n_pbs_adjusted;

            p.Save();
        }

        static DTE GetDTE(string solutionfile)
        {
            DTE dte = null;
            try
            {                
                dte = (DTE)System.Runtime.InteropServices.Marshal.GetActiveObject(
                    FixSolution.Properties.Settings.Default.ROT_PROG_ID);
            }
            catch (Exception)
            {
                Console.WriteLine("Could not get an instance of an already running Visual Studio. Trying to start a new one");
            }
            if (dte == null)
            {
                Type visualStudioType = Type.GetTypeFromProgID(
                    FixSolution.Properties.Settings.Default.ROT_PROG_ID);
                dte = Activator.CreateInstance(visualStudioType) as DTE;
            }
            if (dte == null)
            {
                Console.WriteLine("Unable to get an instance of Visual Studio");
            }
            else
            {
                dte.MainWindow.Visible = true;
                dte.Solution.Open(solutionfile);
            }
            return dte;
        }

        static void ProcessSolution(string solutionfile)
        {
            DTE dte = GetDTE(solutionfile);

            foreach (Project pp in dte.Solution.Projects)
            {
                if (pp.Kind == FixSolution.Properties.Settings.Default.SF_GUID)
                    ProcessSolutionFolder(pp);
                else
                    ProcessProject(pp);
            }
            Console.WriteLine(string.Format("\nn_projects={0}, n_projects_cpp={1}, n_pbs_adjusted={2}, n_ps_adjusted={3}; n_consistency_errors={4}",
                _stats.n_projects, _stats.n_projects_cpp, _stats.n_pbs_adjusted, _stats.n_ps_adjusted, _stats.n_consistency_errors));
            dte.Solution.Close();
        }

        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine(@"Usage: FixSolution c:\full\path\to\YourSolution.sln");
            }

            var solutionfile = args[0];

            ProcessSolution(solutionfile);
        }
    }
}

App.config中:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="FixSolution.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        </sectionGroup>
    </configSections>
    <applicationSettings>
        <FixSolution.Properties.Settings>
            <setting name="AbsoluteVspropsPath" serializeAs="String">
                <value>c:\svn\mainline\ourbuild.vsprops</value>
            </setting>
            <setting name="SF_GUID" serializeAs="String">
                <value>{66A26720-8FB5-11D2-AA7E-00C04F688DDE}</value>
            </setting>
            <setting name="STD_TARGET" serializeAs="String">
                <value>c:\apps\ourapp</value>
            </setting>
            <setting name="ROT_PROG_ID" serializeAs="String">
                <value>VisualStudio.DTE.9.0</value>
            </setting>
        </FixSolution.Properties.Settings>
    </applicationSettings>
</configuration>

ourbuild.vsprops

<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioPropertySheet
    ProjectType="Visual C++"
    Version="8.00"
    Name="build"
    >
    <UserMacro
        Name="THETARGETDIR"
        Value="c:\apps\ourapp"
        PerformEnvironmentSet="true"
    />
</VisualStudioPropertySheet>