捕获 Visual Studio 2015 年的解决方案事件

Capture solution events in Visual Studio 2015

我正在开发一个 Visual Studio 插件。我想捕获打开新解决方案的事件。为了实现这一点,我实现了 IVsSolutionEvents 接口并使用 AdviseSolutionEvents() 注册了它。但是,当我 运行 测试 VS 实例并打开解决方案时,没有调用正确的事件方法。

这是我的代码:

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;
        }
}

为什么 OnAfterOpenSolution() 从未被调用过?

你试过在2015下Microsoft.VisualStudio.Shell.Interop命名空间的IVsSolutionEvents2接口吗?

无视,这个方法在你使用的界面上。

您的实施是什么样的?

这是一个通过抽象 class 实现的示例:

   [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;
                }
            }
        }
    }

好的,我明白了。

事实证明,默认情况下,Visual Studio 包不会在启动时加载,以避免消耗内存和 CPU。相反,Visual Studio 在需要时加载它们。因此,之前没有注册事件。

要更改此行为,必须将 ProvideAutoLoad 属性添加到 class 定义:

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

此属性的值是一个带有 Guid 标识 UI 上下文的字符串,例如没有打开解决方案的上下文。

Source