最近在做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); } }