现在的位置: 首页 > 综合 > 正文

运用EnvDTE获取Visual Studio实例并动态修改解决方案和项目

2018年04月07日 ⁄ 综合 ⁄ 共 2784字 ⁄ 字号 评论关闭

    最近在做Visual Studio项目和项模板需要用到一些EnvDTE的技术,把相关代码拿出来和大家分享一下

首先是获取Visual Studio实例

在仅打开了一个实例的情况下,用GetActiveInstance即可,

在打开了多个实例的情况下,可以用另外一个函数获得所有实例

这里有一个问题,如果打开了多个Visual Studio,如何知道当前正在操作的Visual Studio实例?

答案令人失望,没有什么好办法。 如果有人知道可以分享一下。

有一个变通的办法,通过打开的解决方案的名称来区分,即通过Solution Name来找到某一个VS的实例。当然,前提是要知道这个Solution的名字,于是又陷入了死循环。

然后就是找到一个特定的项目(需要传入项目特征字符或者完整名称)

然后把文件或者引用加到项目中

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using EnvDTE;
using EnvDTE80;
using VSLangProj;

namespace Template.AddNewItemWizard
{
    class EnvDTEHelper
    {

        public static void AddFilesToProject(string projectName, List<string> files)
        {
            try
            {
                DTE dte = GetIntegrityServiceInstance();
                if (dte != null)
                {
                    foreach (EnvDTE.Project item in dte.Solution.Projects)
                    {
                        if (item.Name.Contains(projectName))
                        {
                            foreach (string file in files)
                                item.ProjectItems.AddFromFile(file);
                            item.Save();
                        }
                    }
                }
            }
            finally
            {
            }
        }

        public static void AddProjectReferences(string projectName, Dictionary<string, string> references)
        {
            try
            {
                DTE dte = GetIntegrityServiceInstance();
                if (dte != null)
                {
                    foreach (EnvDTE.Project item in dte.Solution.Projects)
                    {
                        if (item.Name.Contains(projectName))
                        {
                            VSProject vsProject = (VSProject)item.Object;
                            foreach (KeyValuePair<string, string> reference in references)
                            {
                                if (vsProject.References.Find(reference.Key) == null)
                                {
                                    vsProject.References.Add(reference.Value);
                                }
                            }
                            item.Save();
                        }
                    }
                }
            }
            finally
            {
            }
        }

        private static DTE GetIntegrityServiceInstance()
        {
            List<string> projectNames = new List<string>();
            IEnumerable<DTE> dtes = GetAllInstances();
            if (dtes.Count() == 1)
                return dtes.First();
            foreach (DTE dte in GetAllInstances())
            {
                projectNames.Clear();
                foreach (Project project in dte.Solution.Projects)
                {
                    projectNames.Add(project.Name);
                }
                if ((projectNames.Contains("Service")) && (projectNames.Contains("NUnit")))
                    return dte;
            }
            return null;
        }

        private static DTE2 GetActiveInstance()
        {
            return (EnvDTE80.DTE2)Marshal.GetActiveObject("VisualStudio.DTE.11.0");
        }

        private static IEnumerable<DTE> GetAllInstances()
        {
            IRunningObjectTable rot;
            IEnumMoniker enumMoniker;
            int retVal = GetRunningObjectTable(0, out rot);

            if (retVal == 0)
            {
                rot.EnumRunning(out enumMoniker);

                IntPtr fetched = IntPtr.Zero;
                IMoniker[] moniker = new IMoniker[1];
                object punkObject = null;
                while (enumMoniker.Next(1, moniker, fetched) == 0)
                {
                    IBindCtx bindCtx;
                    CreateBindCtx(0, out bindCtx);
                    string displayName;
                    moniker[0].GetDisplayName(bindCtx, null, out displayName);
                   // Console.WriteLine("Display Name: {0}", displayName);
                    bool isVisualStudio = displayName.StartsWith("!VisualStudio");
                    if (isVisualStudio)
                    {
                        //var dte = rot.GetObject(moniker) as DTE;
                        //yield return dte;
                        rot.GetObject(moniker[0], out punkObject);
                        var dte = (DTE)(punkObject);
                        yield return dte;
                    }
                }
            }
        }

        [DllImport("ole32.dll")]
        private static extern void CreateBindCtx(int reserved, out IBindCtx ppbc);

        [DllImport("ole32.dll")]
        private static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);
    }
}

抱歉!评论已关闭.