2017-05-22 3 views
1

솔루션이 완전히로드되면 알림을 받고 싶습니다. 이 answer에 영감을 얻어 IVsSolutionEvents을 구현하려고했습니다. VSPackage 용 솔루션이로드 될 때 알림을 받으려면 어떻게해야합니까?

내가이 개 C# 프로젝트와 솔루션을로드

로딩이 완료 될 때까지 기다렸다가 마침내 가까운 비주얼 스튜디오 2017의 출력은 다음과 같은 추적 메시지를 보여줍니다

VSTestPackage1: OnAfterOpenProject 
VSTestPackage1: OnQueryCloseSolution 
VSTestPackage1: OnQueryCloseProject 
VSTestPackage1: OnQueryCloseProject 
VSTestPackage1: OnBeforeCloseSolution 
VSTestPackage1: OnQueryCloseProject 
VSTestPackage1: OnBeforeCloseProject 
VSTestPackage1: OnQueryCloseProject 
VSTestPackage1: OnBeforeCloseProject 
VSTestPackage1: OnAfterCloseSolution 

이 예상 된 행동인가를? OnAfterOpenSolution이 호출되지 않는 이유는 무엇입니까? 디자인에 의해

[PackageRegistration(UseManagedResourcesOnly = true)] 
[InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] 
[Guid(PackageGuidString)] 
[SuppressMessage("StyleCop.CSharp.DocumentationRules", "SA1650:ElementDocumentationMustBeSpelledCorrectly", 
    Justification = "pkgdef, VS and vsixmanifest are valid VS terms")] 
[ProvideAutoLoad(VSConstants.UICONTEXT.SolutionHasMultipleProjects_string)] 
public sealed class VSPackage1 : Package, IVsSolutionEvents 
{ 
    public const string PackageGuidString = "2e655097-9510-4cf8-b9d4-ceeacebbaf3c"; 

    private DTE _dte; 
    private uint _hSolutionEvents = uint.MaxValue; 
    private IVsSolution _solution; 

    /// <summary> 
    ///  Initialization of the package; this method is called right after the package is sited, so this is the place 
    ///  where you can put all the initialization code that rely on services provided by VisualStudio. 
    /// </summary> 
    protected override void Initialize() 
    { 
     base.Initialize(); 

     _dte = (DTE) GetService(typeof(DTE)); 

     AdviseSolutionEvents(); 
    } 

    protected override void Dispose(bool disposing) 
    { 
     UnadviseSolutionEvents(); 

     base.Dispose(disposing); 
    } 

    private void AdviseSolutionEvents() 
    { 
     UnadviseSolutionEvents(); 

     _solution = GetService(typeof(SVsSolution)) as IVsSolution; 

     _solution?.AdviseSolutionEvents(this, out _hSolutionEvents); 
    } 

    private void UnadviseSolutionEvents() 
    { 
     if (_solution == null) return; 
     if (_hSolutionEvents != uint.MaxValue) 
     { 
      _solution.UnadviseSolutionEvents(_hSolutionEvents); 
      _hSolutionEvents = uint.MaxValue; 
     } 

     _solution = null; 
    } 

    #region Implementation of IVsSolutionEvents 

    int IVsSolutionEvents.OnAfterOpenProject(IVsHierarchy pHierarchy, int fAdded) 
    { 
     Trace.WriteLine("OnAfterOpenProject", "VSTestPackage1"); 
     return VSConstants.S_OK; 
    } 

    int IVsSolutionEvents.OnQueryCloseProject(IVsHierarchy pHierarchy, int fRemoving, ref int pfCancel) 
    { 
     Trace.WriteLine("OnQueryCloseProject", "VSTestPackage1"); 
     return VSConstants.S_OK; 
    } 

    int IVsSolutionEvents.OnBeforeCloseProject(IVsHierarchy pHierarchy, int fRemoved) 
    { 
     Trace.WriteLine("OnBeforeCloseProject", "VSTestPackage1"); 
     return VSConstants.S_OK; 
    } 

    int IVsSolutionEvents.OnAfterLoadProject(IVsHierarchy pStubHierarchy, IVsHierarchy pRealHierarchy) 
    { 
     Trace.WriteLine("OnAfterLoadProject", "VSTestPackage1"); 
     return VSConstants.S_OK; 
    } 

    int IVsSolutionEvents.OnQueryUnloadProject(IVsHierarchy pRealHierarchy, ref int pfCancel) 
    { 
     Trace.WriteLine("OnQueryUnloadProject", "VSTestPackage1"); 
     return VSConstants.S_OK; 
    } 

    int IVsSolutionEvents.OnBeforeUnloadProject(IVsHierarchy pRealHierarchy, IVsHierarchy pStubHierarchy) 
    { 
     Trace.WriteLine("OnBeforeUnloadProject", "VSTestPackage1"); 
     return VSConstants.S_OK; 
    } 

    int IVsSolutionEvents.OnAfterOpenSolution(object pUnkReserved, int fNewSolution) 
    { 
     Trace.WriteLine("OnAfterOpenSolution", "VSTestPackage1"); 
     return VSConstants.S_OK; 
    } 

    int IVsSolutionEvents.OnQueryCloseSolution(object pUnkReserved, ref int pfCancel) 
    { 
     Trace.WriteLine("OnQueryCloseSolution", "VSTestPackage1"); 
     return VSConstants.S_OK; 
    } 

    int IVsSolutionEvents.OnBeforeCloseSolution(object pUnkReserved) 
    { 
     Trace.WriteLine("OnBeforeCloseSolution", "VSTestPackage1"); 
     return VSConstants.S_OK; 
    } 

    int IVsSolutionEvents.OnAfterCloseSolution(object pUnkReserved) 
    { 
     Trace.WriteLine("OnAfterCloseSolution", "VSTestPackage1"); 
     return VSConstants.S_OK; 
    } 

    #endregion 
} 
+1

왜 UICONTEXT_SolutionExists를 사용하지 않는? –

+0

내가 개발중인 패키지는 여러 프로젝트가있는 솔루션에만 의미가있는 기능을 제공합니다. 나는'[ProvideAutoLoad]'에 대한이 인수가 솔루션 이벤트에 미치는 영향을 알지 못했습니다. 당신의 힌트를 가져 주셔서 감사합니다. – CodeFox

답변

3

예,이 :

패키지 구현입니다. 관찰 된 동작의 이유는 패키지가로드되기 전에 해당 이벤트가 실행되기 때문입니다. 이벤트가 발생했는지, 솔루션을 닫은 후 (패키지를로드 한 후) 다시 열 때 관찰하여 쉽게 테스트 할 수 있습니다. 2 차로 돌아 가면 화재가 발생합니다.

이 예에서는 SolutionHasMultipleProjects 컨텍스트 GUID를 사용하고 있습니다.이 경우 솔루션에 여러 프로젝트가있는 경우에만 패키지가로드됩니다. IDE가이를 결정하는 유일한 방법은 먼저 솔루션로드가 있고 UI 컨텍스트를 설정하는 것입니다. 기본적으로 이벤트 핸들러를 설정하는 것은 너무 늦습니다.

특정 알림을 받으려면 NoSolution_string 및 SolutionExists_string을 사용하여로드하도록 패키지를 등록 할 수 있습니다. 그러나 이것은 다소 악의적인데, 패키지가 항상로드되도록 강제하기 때문에 (필요하지 않은 경우에도) 패키지는 덜 바람직한 솔루션입니다.

SolutionExistsAndFullyLoadedContext를 사용하면 더 좋은 방법 일 수 있습니다. 패키지가 처음로드되면 조건이 충족되었음을 알게되고 패키지의 Initialize 재정의에서 돌아 오기 바로 전에 핸들러 코드를 실행할 수 있습니다. 그리고 이후의 솔루션로드시 원래의 IVsSolutionEvents 핸들러가 호출됩니다.

또한 아래에 설명 된대로 규칙 기반 UI 컨텍스트를 사용하여/등록 고려할 수 있습니다 : 감사합니다

How to: Use Rule-based UI Context for Visual Studio Extensions

, 에드 도레을

+0

위대한 설명 -'[ProvideAutoLoad]'에 대한'UIContext'가 이벤트 처리에 어떻게 영향을 미치는지 알지 못했습니다. _rule 기반 UI 컨텍스트 _을 언급 해 주셔서 감사합니다! – CodeFox

관련 문제