捕获 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 上下文的字符串,例如没有打开解决方案的上下文。
我正在开发一个 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 上下文的字符串,例如没有打开解决方案的上下文。