如何在 Debug > Windows 菜单中添加仅在断点显示的菜单命令?

How to add menu command in Debug > Windows menu showing only in breakpoint?

我正在创建一个包含工具 Window 的 VSIX。我想将打开它的菜单项移动到 Debug > Windows,而不是 View > Other Windows。我还想仅在目标项目处于调试模式时显示它(例如调用堆栈菜单项)。

我设法在“调试”菜单中显示了菜单项,但在“调试”> Windows 中却没有。在我的 .vsct 中,我使用了:

<!-- ... -->
<Extern href="VSDbgCmd.h"/>
<Extern href="VsDebugGuids.h"/>
<!-- ... -->
<Parent guid="guidVSDebugGroup" id="IDM_DEBUG_WINDOWS"/>
<!-- ... -->

关于仅在调试模式下显示它,我没有任何想法,也找不到任何有用的东西。

所以我的问题是:如何让我的菜单项表现得像调用堆栈菜单项(在调试 > Window 中并且仅在调试模式下显示)?

虽然有一个 UI“调试”上下文,但似乎没有用于调试器实际进入中断模式的上下文。 (提示,我使用 https://marketplace.visualstudio.com/items?itemName=PaulHarrington.ComponentDiagnostics 扩展来监视活动的 UI 上下文)

因此您需要向按钮添加 DynamicVisibility 和 DefaultInvisible 命令标志:

  <Extern href="stdidcmd.h"/>
  <Extern href="vsshlids.h"/>
  <Extern href="VSDbgCmd.h"/>
  <Extern href="VsDebugGuids.h"/>
  <Commands package="guidIaxToolWindowPackage">
    <Buttons>
      <Button guid="guidIaxToolWindowPackageCmdSet" id="IaxToolWindowCommandId" priority="0x0002" type="Button">
        <Parent guid="guidVSDebugGroup" id="IDG_DEBUG_WINDOWS_GENERAL"/>
        <Icon guid="guidImages" id="bmpPic1" />
        <CommandFlag>DynamicVisibility</CommandFlag>
        <CommandFlag>DefaultInvisible</CommandFlag>
        <Strings>
          <ButtonText>Show IaxToolWindow</ButtonText>
        </Strings>
      </Button>
    </Buttons>

然后,通过使用下面的 ProvideAutoLoad 属性修饰 AsyncPackage class,确保在调试器附加到或启动进程时加载包:

namespace IaxToolwindow
{
    // use Debugging UI Context to ensure package get loaded when debugging starts
    [ProvideAutoLoad(VSConstants.UICONTEXT.Debugging_string, PackageAutoLoadFlags.BackgroundLoad)]
    [PackageRegistration(UseManagedResourcesOnly = true, AllowsBackgroundLoading = true)]
    [InstalledProductRegistration("#110", "#112", "1.0", IconResourceID = 400)] // Info on this package for Help/About
    [ProvideMenuResource("Menus.ctmenu", 1)]
    [ProvideToolWindow(typeof(IaxToolWindow))]
    [Guid(IaxToolWindowPackage.PackageGuidString)]
    public sealed class IaxToolWindowPackage : AsyncPackage
    {
        public const string PackageGuidString = "256ca1a6-6b6d-4329-a7f9-15ee5bbf8114";

然后为您的菜单命令添加一个 BeforeQueryStatus 命令处理程序,使菜单项在 IVSDebugger.GetMode returns DBGMODE_BREAK 时可见。例如:

private IaxToolWindowCommand(AsyncPackage package, OleMenuCommandService commandService)
{
    this.package = package ?? throw new ArgumentNullException(nameof(package));
    commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));

    var menuCommandID = new CommandID(CommandSet, CommandId);
    var menuItem = new OleMenuCommand(this.Execute, menuCommandID);
    menuItem.BeforeQueryStatus += IAxToolWindowCommand_BeforeQueryStatus;
    commandService.AddCommand(menuItem);
}

private void IAxToolWindowCommand_BeforeQueryStatus(object sender, EventArgs e)
{
    ThreadHelper.JoinableTaskFactory.Run(async delegate 
    {
        await Microsoft.VisualStudio.Shell.ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
        OleMenuCommand menuItem = (OleMenuCommand)sender;
        IVsDebugger vsDebugger = await ServiceProvider.GetServiceAsync(typeof(IVsDebugger)) as IVsDebugger;
        Assumes.Present(vsDebugger);
        DBGMODE[] dbgmode = new DBGMODE[1];
        int hr = vsDebugger.GetMode(dbgmode);
        // show menu item when debugger is in break mode
        menuItem.Visible = (dbgmode[0] == DBGMODE.DBGMODE_Break);
    });
}

这是基于向导生成的 AsyncToolwindow 项目构建的。但请注意,我将 MenuCommand 更改为 OleMenuCommand,因此我们可以添加并使用 BeforeQueryStatus 处理程序来控制菜单项的可见性。

ProvideAutoLoad 用于确保在启动调试会话时加载包,因此它会及时启动以使菜单项可见(当调试器处于中断模式时)。

如果在调试器进入中断模式时激活了一个 UIContext guid,我们可以向 .vsct 添加一个 VisbilityConstraint。但是由于缺少特定于中断模式的 UIContext,您需要执行与上述类似的操作,使菜单项仅在中断模式下可见。

此致,