【问题标题】:Capture solution events in Visual Studio 2015在 Visual Studio 2015 中捕获解决方案事件
【发布时间】:2016-04-11 08:24:54
【问题描述】:

我正在开发一个 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()

【问题讨论】:

    标签: c# visual-studio-2015 visual-studio-extensions


    【解决方案1】:

    好的,我想通了。

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

    要改变这种行为,必须在类定义中添加ProvideAutoLoad 属性:

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

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

    Source

    【讨论】:

    • 根据您要执行的操作,您也可以在 SolutionExists 上使用 ProvideAutoload,它会在解决方案加载时加载您。这样你就不会在启动时运行只是为了等待我们可以告诉你另一种方式的事件。
    【解决方案2】:

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

    不管,这个方法在你使用的界面上。

    你的实现是什么样的?

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

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

    【讨论】:

    • 谢谢,但我发现我的代码出了什么问题。
    • 很高兴你让它工作了,是的,延迟加载就可以了。但我很感谢这样的小事,让整体编辑体验更好。我仍然记得启动 VS 需要多长时间,或者单击“添加引用”并盯着锁定的屏幕几分钟直到出现一些东西。越来越好,只需要记住这样的事情的所有细节。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    • 2015-10-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-30
    • 2016-01-18
    相关资源
    最近更新 更多