2016-04-11 18 views
0

Ich entwickle ein Visual Studio-Plug-in. Ich möchte das Ereignis der Eröffnung einer neuen Lösung erfassen. Um dies zu erreichen, implementierte ich die Schnittstelle IVsSolutionEvents und registrierte sie mit AdviseSolutionEvents(). Wenn ich jedoch Testinstanz von VS ausführe und eine Lösung öffne, wird die richtige Ereignismethode nicht aufgerufen.Erfassen von Lösungsereignissen in Visual Studio 2015

Hier ist mein Code:

public sealed class MyPackage : Package, IVsSolutionEvents 
{ 
     // ... 

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

      IVsSolution solution = GetService(typeof(SVsSolution)) as IVsSolution; 
      uint cookie = 0; 
      solution.AdviseSolutionEvents(this, out cookie); 
     } 

     // ... 

     public int OnAfterOpenSolution(object pUnkReserved, int fNewSolution) 
     { 
      MessageBox.Show("Opened a solution!"); 
      return VSConstants.S_OK; 
     } 
} 

Warum ist OnAfterOpenSolution() nie genannt?

Antwort

2

Haben Sie dies mit der IVsSolutionEvents2 Schnittstelle im Namespace Microsoft.VisualStudio.Shell.Interop unter 2015 versucht?

Nicht berücksichtigt, diese Methode ist auf der Schnittstelle, die Sie verwenden.

Wie sieht Ihre Implementierung aus?

Hier ist ein Beispiel-Implementierung über eine abstrakte Klasse:

[CLSCompliant(false)] 
    public abstract class SolutionListener : IVsSolutionEvents, IVsSolutionEvents2, IVsSolutionEvents3, IVsSolutionEvents4, IDisposable 
    { 
     public IServiceProvider ServiceProvider { get; private set; } 

     public IVsSolution Solution { get; private set; } 

     private uint eventsCookie = (uint)ShellConstants.VSCOOKIE_NIL; 
     private bool isDisposed; 
     private static volatile object Mutex = new object(); 

     protected SolutionListener(IServiceProvider serviceProvider) 
     { 
      ServiceProvider = serviceProvider; 

      Solution = serviceProvider.GetService(typeof(SVsSolution)) as IVsSolution; 
      Debug.Assert(Solution != null, "Could not get the IVsSolution object"); 
      if (Solution == null) 
      { 
       throw new InvalidOperationException(); 
      } 
     } 

     public abstract int OnAfterCloseSolution(object reserved); 
     public abstract int OnAfterClosingChildren(IVsHierarchy hierarchy); 
     public abstract int OnAfterLoadProject(IVsHierarchy stubHierarchy, IVsHierarchy realHierarchy); 
     public abstract int OnAfterMergeSolution(object pUnkReserved); 
     public abstract int OnAfterOpenProject(IVsHierarchy hierarchy, int added); 
     public abstract int OnAfterOpenSolution(object pUnkReserved, int fNewSolution); 
     public abstract int OnAfterOpeningChildren(IVsHierarchy hierarchy); 
     public abstract int OnBeforeCloseProject(IVsHierarchy hierarchy, int removed); 
     public abstract int OnBeforeCloseSolution(object pUnkReserved); 
     public abstract int OnBeforeClosingChildren(IVsHierarchy hierarchy); 
     public abstract int OnBeforeOpeningChildren(IVsHierarchy hierarchy); 
     public abstract int OnBeforeUnloadProject(IVsHierarchy realHierarchy, IVsHierarchy rtubHierarchy); 
     public abstract int OnQueryCloseProject(IVsHierarchy hierarchy, int removing, ref int cancel); 
     public abstract int OnQueryCloseSolution(object pUnkReserved, ref int cancel); 
     public abstract int OnQueryUnloadProject(IVsHierarchy pRealHierarchy, ref int cancel); 
     public abstract int OnAfterAsynchOpenProject(IVsHierarchy hierarchy, int added); 
     public abstract int OnAfterChangeProjectParent(IVsHierarchy hierarchy); 
     public abstract int OnAfterRenameProject(IVsHierarchy hierarchy); 
     public abstract int OnQueryChangeProjectParent(IVsHierarchy hierarchy, IVsHierarchy newParentHier, ref int cancel); 

     public virtual void Initialize() 
     { 
      if (Solution != null && eventsCookie == (uint)ShellConstants.VSCOOKIE_NIL) 
      { 
       ErrorHandler.ThrowOnFailure(Solution.AdviseSolutionEvents(this, out eventsCookie)); 
      } 
     } 

     public void Dispose() 
     { 
      Dispose(true); 
      GC.SuppressFinalize(this); 
     } 

     protected virtual void Dispose(bool disposing) 
     { 
      if (!isDisposed) 
      { 
       lock (Mutex) 
       { 
        if (disposing && Solution != null && eventsCookie != (uint)ShellConstants.VSCOOKIE_NIL) 
        { 
         ErrorHandler.ThrowOnFailure(Solution.UnadviseSolutionEvents((uint)eventsCookie)); 
         eventsCookie = (uint)ShellConstants.VSCOOKIE_NIL; 
        } 
        isDisposed = true; 
       } 
      } 
     } 
    } 
+0

Danke, aber ich herausgefunden, was mit meinem Code falsch war. – Kao

+1

Froh, dass es funktioniert, und ja, verzögertes Laden würde es tun. Aber ich bin dankbar für kleine Dinge wie diese, um die gesamte Editor-Erfahrung besser zu machen. Ich erinnere mich noch daran, wie lange es dauern würde, VS zu starten oder auf "Add Reference" zu klicken und Minuten lang auf einen gesperrten Bildschirm zu starren, bis etwas auftauchte. Es wird besser, denke nur an all die Details für solche Dinge. – Patrick

2

OK, ich habe es herausgefunden.

Es stellt sich heraus, dass Visual Studio-Pakete standardmäßig nicht beim Start geladen werden, um Speicher und CPU zu verbrauchen. Stattdessen lädt Visual Studio sie bei Bedarf. Aus diesem Grund werden Ereignisse nicht vorher registriert.

Um dieses Verhalten eine haben zu ändern, um Klassendefinition hinzufügen ProvideAutoLoad Attribut:

[ProvideAutoLoad(VSConstants.UICONTEXT.NoSolution_string)] 
public sealed class Command1Package : Package 
... 

Der Wert dieses Attributs ist ein String mit Guid UI Kontext zu identifizieren, zum Beispiel Zusammenhang mit keine Lösungen eröffnet.

Source

+1

Je nachdem, was Sie zu tun versuchen, können Sie ProvideAutoload auch in SolutionExists verwenden, wodurch Sie beim Laden der Lösung geladen werden. Auf diese Weise laufen Sie nicht beim Start, nur um auf ein Ereignis zu warten, das wir Ihnen über einen anderen Weg erzählen können. –