我如何从我的 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.OnBuildBegin
或 BuildEvents.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;
}
在我的机器上,事件的顺序如下:
- OnBeforeExecute
Debug.Start
- OnBuildBegin
- OnAfterExecute
Debug.Start
- OnBuildDone
所以,如果您看到这个序列,它后面将是一个调试会话。
完成 Serge 的回答。其实我遵守这个顺序:
- OnBeforeExecute
Debug.Start
- OnAfterExecute
Debug.Start
- OnBuildBegin
- OnBuildDone
此外,如果 VisualStudio 估计它在调试之前没有要构建的内容,则跳过 OnBuildBegin
。
OnBuildBegin
或(如果跳过)OnBuildDone
总是在 OnAfterExecute Debug.Start
之后执行(在 VS2010/2012/2013/2015 上测试)。
监视其他命令,我可以看到两个命令 Build.SolutionConfigurations
(有时还有一个或几个 Debug.StartupProject
)在 运行 之间 before/after 执行 Debug.Start
(我只在 VS2013/2015 中观察到这种行为)。
- OnBeforeExecute
Debug.Start
- OnBeforeExecute
Build.SolutionConfigurations
- OnAfterExecute
Build.SolutionConfigurations
- OnBeforeExecute
Build.SolutionConfigurations
- OnAfterExecute
Build.SolutionConfigurations
- OnBeforeExecute
Debug.StartupProjects
- OnAfterExecute
Debug.StartupProjects
- OnAfterExecute
Debug.Start
- OnBuildBegin
- OnBuildDone
因此我们可以推断,成功构建后会出现调试会话,当以下两个事件之一发生时:
- 当
Build.SolutionConfigurations
或 Debug.StartupProjects
命令在 before/after Debug.Start
命令之间触发时。
- 当上次 OnAfterExecute
Debug.Start
和当前 OnBuildBegin
或 OnBuildDone
. 之间的时间少于一秒时
作为旁注,命令 Debug.StartWithoutDebugging
与 Debug.Start
起着相同的作用,当用户要求在不调试的情况下启动时。因此我们也可以推断 成功的构建之后将是 运行 (没有调试)会话
如果因为用户想要启动调试会话而触发构建,我希望我的 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.OnBuildBegin
或 BuildEvents.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;
}
在我的机器上,事件的顺序如下:
- OnBeforeExecute
Debug.Start
- OnBuildBegin
- OnAfterExecute
Debug.Start
- OnBuildDone
所以,如果您看到这个序列,它后面将是一个调试会话。
完成 Serge 的回答。其实我遵守这个顺序:
- OnBeforeExecute
Debug.Start
- OnAfterExecute
Debug.Start
- OnBuildBegin
- OnBuildDone
此外,如果 VisualStudio 估计它在调试之前没有要构建的内容,则跳过 OnBuildBegin
。
OnBuildBegin
或(如果跳过)OnBuildDone
总是在 OnAfterExecute Debug.Start
之后执行(在 VS2010/2012/2013/2015 上测试)。
监视其他命令,我可以看到两个命令 Build.SolutionConfigurations
(有时还有一个或几个 Debug.StartupProject
)在 运行 之间 before/after 执行 Debug.Start
(我只在 VS2013/2015 中观察到这种行为)。
- OnBeforeExecute
Debug.Start
- OnBeforeExecute
Build.SolutionConfigurations
- OnAfterExecute
Build.SolutionConfigurations
- OnBeforeExecute
Build.SolutionConfigurations
- OnAfterExecute
Build.SolutionConfigurations
- OnBeforeExecute
Debug.StartupProjects
- OnAfterExecute
Debug.StartupProjects
- OnAfterExecute
Debug.Start
- OnBuildBegin
- OnBuildDone
因此我们可以推断,成功构建后会出现调试会话,当以下两个事件之一发生时:
- 当
Build.SolutionConfigurations
或Debug.StartupProjects
命令在 before/afterDebug.Start
命令之间触发时。 - 当上次 OnAfterExecute
Debug.Start
和当前OnBuildBegin
或OnBuildDone
. 之间的时间少于一秒时
作为旁注,命令 Debug.StartWithoutDebugging
与 Debug.Start
起着相同的作用,当用户要求在不调试的情况下启动时。因此我们也可以推断 成功的构建之后将是 运行 (没有调试)会话