我如何从我的 VSIX 知道生成后将进行调试会话?

How do I know from my VSIX that a build will be followed by a Debug session?

如果因为用户想要启动调试会话而触发构建,我希望我的 VSIX 在我的 BuildEvents.OnBuildDone 处理程序中做一些不同的事情。

我试过了...

private void m_BuildEvents_OnBuildDone(vsBuildScope scope, vsBuildAction action) {
   if (m_DTE.Mode == vsIDEMode.vsIDEModeDebug) {
      //...
   }
}

...但不幸的是,此时 m_DTE.Mode 还不等于 vsIDEMode.vsIDEModeDebug

我可以启动一个一两秒的计时器,然后检查是否 (m_DTE.Mode == vsIDEMode.vsIDEModeDebug) 但这不是一个干净可靠的解决方案。

我可以通过在 BuildEvents.OnBuildBeginBuildEvents.OnBuildDone 处理程序中以某种方式查询 VSIX API 知道成功构建之后会进行调试会话吗?

您可以使用 EnvDTE.CommandEvents 监控 Debug.Start 命令调用。请参阅 Visual Commander 的以下示例 C# 扩展:

public class E : VisualCommanderExt.IExtension
{
    public void SetSite(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
    {
        events = DTE.Events;
        commandEvents = events.get_CommandEvents(null, 0);
        buildEvents = events.BuildEvents;
        commands = DTE.Commands as EnvDTE80.Commands2;

        commandEvents.BeforeExecute += OnBeforeExecute;
        commandEvents.AfterExecute += OnAfterExecute;

        buildEvents.OnBuildDone += OnBuildDone;
        buildEvents.OnBuildBegin += OnBuildBegin;
    }

    public void Close()
    {
        commandEvents.BeforeExecute -= OnBeforeExecute;
        commandEvents.AfterExecute -= OnAfterExecute;

        buildEvents.OnBuildDone -= OnBuildDone;
        buildEvents.OnBuildBegin -= OnBuildBegin;
    }

    private void OnBeforeExecute(string Guid, int ID, object CustomIn, object CustomOut, ref bool CancelDefault)
    {
        string name = GetCommandName(Guid, ID);
        if (name == "Debug.Start")
        {
            System.Windows.MessageBox.Show("OnBeforeExecute Debug.Start");
        }
    }

    private void OnAfterExecute(string Guid, int ID, object CustomIn, object CustomOut)
    {
        string name = GetCommandName(Guid, ID);
        if (name == "Debug.Start")
        {
            System.Windows.MessageBox.Show("OnAfterExecute Debug.Start " + System.DateTime.Now.Second + "." + System.DateTime.Now.Millisecond);
        }
    }

    private void OnBuildDone(EnvDTE.vsBuildScope scope, EnvDTE.vsBuildAction action)
    {
        System.Windows.MessageBox.Show("OnBuildDone " + System.DateTime.Now.Second + "." + System.DateTime.Now.Millisecond);
    }

    private void OnBuildBegin(EnvDTE.vsBuildScope scope, EnvDTE.vsBuildAction action)
    {
        System.Windows.MessageBox.Show("OnBuildBegin " + System.DateTime.Now.Second + "." + System.DateTime.Now.Millisecond);
    }

    // throw()
    private string GetCommandName(string Guid, int ID)
    {
        if (Guid == null)
            return "null";

        string result = "";
        if (commands != null)
        {
            try
            {
                return commands.Item(Guid, ID).Name;
            }
            catch (System.Exception)
            {
            }
        }
        return result;
    }

    private EnvDTE.Events events;
    private EnvDTE.CommandEvents commandEvents;
    private EnvDTE.BuildEvents buildEvents;
    private EnvDTE80.Commands2 commands;
}

在我的机器上,事件的顺序如下:

  1. OnBeforeExecute Debug.Start
  2. OnBuildBegin
  3. OnAfterExecute Debug.Start
  4. OnBuildDone

所以,如果您看到这个序列,它后面将是一个调试会话。


完成 Serge 的回答。其实我遵守这个顺序:

  1. OnBeforeExecute Debug.Start
  2. OnAfterExecute Debug.Start
  3. OnBuildBegin
  4. OnBuildDone

此外,如果 VisualStudio 估计它在调试之前没有要构建的内容,则跳过 OnBuildBegin

OnBuildBegin 或(如果跳过)OnBuildDone 总是在 OnAfterExecute Debug.Start 之后执行(在 VS2010/2012/2013/2015 上测试)。

监视其他命令,我可以看到两个命令 Build.SolutionConfigurations(有时还有一个或几个 Debug.StartupProject)在 运行 之间 before/after 执行 Debug.Start(我只在 VS2013/2015 中观察到这种行为)。

  1. OnBeforeExecute Debug.Start
  2. OnBeforeExecute Build.SolutionConfigurations
  3. OnAfterExecute Build.SolutionConfigurations
  4. OnBeforeExecute Build.SolutionConfigurations
  5. OnAfterExecute Build.SolutionConfigurations
  6. OnBeforeExecute Debug.StartupProjects
  7. OnAfterExecute Debug.StartupProjects
  8. OnAfterExecute Debug.Start
  9. OnBuildBegin
  10. OnBuildDone

因此我们可以推断,成功构建后会出现调试会话,当以下两个事件之一发生时:

  • Build.SolutionConfigurationsDebug.StartupProjects 命令在 before/after Debug.Start 命令之间触发时。
  • 当上次 OnAfterExecute Debug.Start 和当前 OnBuildBeginOnBuildDone.
  • 之间的时间少于一秒时

作为旁注,命令 Debug.StartWithoutDebuggingDebug.Start 起着相同的作用,当用户要求在不调试的情况下启动时。因此我们也可以推断 成功的构建之后将是 运行 (没有调试)会话