2016-08-24 6 views
1

나는 MSDN's Hello World guide to developing Visual Studio extensions을 따라갔습니다 (이 기사에서는 Visual Studio 도구 모음 명령으로 만드는 방법을 설명합니다).EnvDTE를 사용하여 현재 솔루션에있는 모든 프로젝트를 나열하려면 어떻게합니까?

현재/활성 솔루션에 포함 된 모든 프로젝트를 나열하려고합니다.

명령 템플릿의 자동 생성 코드에 있습니다.

나는 EnvDTESolutionProjects 속성을 시도했지만 프로젝트가 없습니다.

또한 ActiveSolutionProjects 속성이 있지만 빈 배열도 표시됩니다.

어떻게 이루어 집니까?

P.S. : docs에서 사용할 버전을 이해하는 것이 혼란하기 때문에 DTE와 DTE2 인터페이스를 모두 시도했습니다. 나는 DTE2를위한 널 서비스를 얻는다, 그래서 나는 DTE에 가고있다.

enter image description here

내 솔루션 탐색기 보이는 같은 :

enter image description here


업데이트 : 버트 Huijben는 gitter/extendvs에서, 상기 VSSDK Extensibility Samples에서 발견, 다음과 같은 제안 -하지만 너무을 작동하지 않습니다 (생성자 및 콜백 함수 내에서 0 요소 반환 이온) : 나를 위해

private Hashtable GetLoadedControllableProjectsEnum() 
{ 
    Hashtable mapHierarchies = new Hashtable(); 

    IVsSolution sol = (IVsSolution)this.ServiceProvider.GetService(typeof(SVsSolution)); 
    Guid rguidEnumOnlyThisType = new Guid(); 
    IEnumHierarchies ppenum = null; 
    ErrorHandler.ThrowOnFailure(sol.GetProjectEnum((uint)__VSENUMPROJFLAGS.EPF_LOADEDINSOLUTION, ref rguidEnumOnlyThisType, out ppenum)); 

    IVsHierarchy[] rgelt = new IVsHierarchy[1]; 
    uint pceltFetched = 0; 
    while (ppenum.Next(1, rgelt, out pceltFetched) == VSConstants.S_OK && 
      pceltFetched == 1) 
    { 
     IVsSccProject2 sccProject2 = rgelt[0] as IVsSccProject2; 
     if (sccProject2 != null) 
     { 
      mapHierarchies[rgelt[0]] = true; 
     } 
    } 

    return mapHierarchies; 
} 
+0

코드를 빨리 훑어 보면 작동해야합니다. 이게 뭐지? 서비스 제공자가 점점? GetService (typeof (SDTE))를 대신 수행하면 캐스트가 그대로 유지됩니다. –

+0

Command1 생성자에서 솔루션이 아직로드되지 않은 것 같습니다. 코드를 MenuItemCallback으로 이동해보십시오. –

+0

@JasonMalinowski :'System .__ ComObject'를 얻습니다. 이것은'Solution' 속성을 포함하고 있으며, 이것은'Projects' 속성을 포함하고 있습니다. 내가 제안한대로 SDTE를 시도했지만 SDTE는 빈 인터페이스이므로 많은 도움이되지 않습니다. – Veverke

답변

1

작품 :

는 DTE에 대한 패키지의 필드를 추가합니다. DTE 서비스를 받으십시오. 솔루션 참조. 당신의 생성자에서

using EnvDTE; 
using EnvDTE80; 

:

dte = this.ServiceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE80.DTE2; 

명령 처리기는 :

Integer count = ((EnvDTE.SolutionClass)dte.Solution).Projects.Count; 

나는이에서 정확한 수를 얻을. 뻔뻔 AutoFindReplace에서 촬영

스크린 샷 (요청)

enter image description here

코드

//------------------------------------------------------------------------------ 
// <copyright file="Command1.cs" company="Company"> 
//  Copyright (c) Company. All rights reserved. 
// </copyright> 
//------------------------------------------------------------------------------ 

using System; 
using System.ComponentModel.Design; 
using System.Globalization; 
using Microsoft.VisualStudio.Shell; 
using Microsoft.VisualStudio.Shell.Interop; 
using EnvDTE; 
using EnvDTE80; 

namespace SolExpExt 
{ 
    internal sealed class Command1 
    { 
     public const int CommandId = 0x0100; 
     public static readonly Guid CommandSet = new Guid("beff5a1a-dff5-4f6a-95c8-fd7ea7411a7b"); 
     private DTE2 dte; 
     private readonly Package package; 
     private IVsSolution sol; 
     private Command1(Package package) 
     { 
      if (package == null) 
      { 
       throw new ArgumentNullException("package"); 
      } 

      this.package = package; 

      OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService; 
      if (commandService != null) 
      { 
       var menuCommandID = new CommandID(CommandSet, CommandId); 
       var menuItem = new MenuCommand(this.MenuItemCallback, menuCommandID); 
       commandService.AddCommand(menuItem); 
      } 

      dte = this.ServiceProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE80.DTE2; 
     } 

     public static Command1 Instance 
     { 
      get; 
      private set; 
     } 

     private IServiceProvider ServiceProvider 
     { 
      get 
      { 
       return this.package; 
      } 
     } 

     public static void Initialize(Package package) 
     { 
      Instance = new Command1(package); 
     } 

     private void MenuItemCallback(object sender, EventArgs e) 
     { 
      string message = $"There are {dte.Solution.Projects.Count} projects in this solution."; 
      string title = "Command1"; 

      VsShellUtilities.ShowMessageBox(
       this.ServiceProvider, 
       message, 
       title, 
       OLEMSGICON.OLEMSGICON_INFO, 
       OLEMSGBUTTON.OLEMSGBUTTON_OK, 
       OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); 
     } 
    } 
} 
+0

코드와 함께 솔루션 탐색기를 보여주는 전체 IDE 창의 스크린 샷을 공유 할 수 있습니까? 위에서 제시 한 내용은 여전히 ​​저에게 효과가 없습니다. 나는 아직도 0 프로젝트를 얻는다. 그래서 1을 얻고 있습니까? – Veverke

+0

@ 버 베크가 그 도움을 주었습니까? –

+0

새 의견을 보내 주셔서 감사합니다. 휴가 중이 었는데이를 확인하고 다시 연락 드리겠습니다. – Veverke

0

다음은, VS2015 커뮤니티를 사용하여 작동 :

using EnvDTE; 
. 
. 
protected override void Initialize() 
{ 
    base.Initialize(); 

    IServiceContainer serviceContainer = this as IServiceContainer; 
    dte = serviceContainer.GetService(typeof(SDTE)) as DTE; 
    var solutionEvents = dte.Events.SolutionEvents; 
    solutionEvents.Opened += OnSolutionOpened; 

    var i = dte.Solution.Projects.Count; // Happy days ! 
} 

모든 코드 라인을 위 0123에 미리 존재한다.내에서 "var i = dte.Solution.Projects"를 제외하고 VSPackage.cs 내에 있습니다.. 카운트;! "난 그냥 라인 44VSPackage.cs에 로컬로 추가하는 나는 다음 solution을 열고 F5를 공격하고, 실험 인스턴스 내에서 내가 JoePublic.Sln을 열고 헤이 프레스토 카운트가 있었다 '2'올바르게 - 빙고 해피 일

2
!

얻을 수있는 EnvDTE.Project 제품 :.

static private void FindProjectsIn(EnvDTE.ProjectItem item, List<EnvDTE.Project> results) 
    { 
     if (item.Object is EnvDTE.Project) 
     { 
      var proj = (EnvDTE.Project)item.Object; 
      if (new Guid(proj.Kind) != Utilities.ProjectTypeGuids.Folder) 
      { 
       results.Add((EnvDTE.Project)item.Object); 
      } 
      else 
      { 
       foreach (EnvDTE.ProjectItem innerItem in proj.ProjectItems) 
       { 
        FindProjectsIn(innerItem, results); 
       } 
      } 
     } 
     if (item.ProjectItems != null) 
     { 
      foreach (EnvDTE.ProjectItem innerItem in item.ProjectItems) 
      { 
       FindProjectsIn(innerItem, results); 
      } 
     } 
    } 

    static private void FindProjectsIn(EnvDTE.UIHierarchyItem item, List<EnvDTE.Project> results) 
    { 
     if (item.Object is EnvDTE.Project) 
     { 
      var proj = (EnvDTE.Project)item.Object; 
      if (new Guid(proj.Kind) != Utilities.ProjectTypeGuids.Folder) 
      { 
       results.Add((EnvDTE.Project)item.Object); 
      } 
      else 
      { 
       foreach (EnvDTE.ProjectItem innerItem in proj.ProjectItems) 
       { 
        FindProjectsIn(innerItem, results); 
       } 
      } 
     } 
     foreach (EnvDTE.UIHierarchyItem innerItem in item.UIHierarchyItems) 
     { 
      FindProjectsIn(innerItem, results); 
     } 
    } 

    static internal IEnumerable<EnvDTE.Project> GetEnvDTEProjectsInSolution() 
    { 
     List<EnvDTE.Project> ret = new List<EnvDTE.Project>(); 
     EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)ServiceProvider.GlobalProvider.GetService(typeof(EnvDTE.DTE)); 
     EnvDTE.UIHierarchy hierarchy = dte.ToolWindows.SolutionExplorer; 
     foreach (EnvDTE.UIHierarchyItem innerItem in hierarchy.UIHierarchyItems) 
     { 
      FindProjectsIn(innerItem, ret); 
     } 
     return ret; 
    } 

특히 재귀 솔루션 폴더로 발굴하는 것이 필요하다

당신은 당신이 승이 작업을 수행 할 수있는 파일 경로를 원하는 경우/DTE 사용 O :

static internal string[] GetProjectFilesInSolution() 
    { 
     IVsSolution sol = ServiceProvider.GlobalProvider.GetService(typeof(SVsSolution)) as IVsSolution; 
     uint numProjects; 
     ErrorHandler.ThrowOnFailure(sol.GetProjectFilesInSolution((uint)__VSGETPROJFILESFLAGS.GPFF_SKIPUNLOADEDPROJECTS, 0, null, out numProjects)); 
     string[] projects = new string[numProjects]; 
     ErrorHandler.ThrowOnFailure(sol.GetProjectFilesInSolution((uint)__VSGETPROJFILESFLAGS.GPFF_SKIPUNLOADEDPROJECTS, numProjects, projects, out numProjects)); 
     //GetProjectFilesInSolution also returns solution folders, so we want to do some filtering 
     //things that don't exist on disk certainly can't be project files 
     return projects.Where(p => !string.IsNullOrEmpty(p) && System.IO.File.Exists(p)).ToArray(); 
    } 
+0

이 재귀 적 솔루션은 다음과 같은 두 가지 문제로 매우 좋습니다. 1. 언로드 된 폴더에서 충돌합니다 (각'var proj = (EnvDTE.Project) item.Object;') 다음에'null '을 확인해야합니다.) 2. 이동합니다 재귀 적으로 솔루션 폴더를 두 번 반복하여 목록에 중복 프로젝트를 작성하므로'foreach (item.UIHierarchyItems의 EnvDTE.UIHierarchyItem innerItem) '및'if (item.ProjectItems! = null)'전에'else'가 필요합니다. –