Hotkeys for Previous and Next call stack frames in Visual Studio

前端 未结 5 903
温柔的废话
温柔的废话 2021-02-01 20:09

Visual Studio gives many navigation hotkeys: F8 for next item in current panel (search results, errors ...), Control+K, N for bookmar

相关标签:
5条回答
  • 2021-02-01 20:33

    I wrote 2 macros to gain it: PreviousStackFrame and NextStackFrame and assigned shortcuts to

    Function StackFrameIndex(ByRef aFrames As EnvDTE.StackFrames, ByRef aFrame As EnvDTE.StackFrame) As Long
        For StackFrameIndex = 1 To aFrames.Count
            If aFrames.Item(StackFrameIndex) Is aFrame Then Exit Function
        Next
        StackFrameIndex = -1
    End Function
    
    Sub NavigateStack(ByVal aShift As Long)
        If DTE.Debugger.CurrentProgram Is Nothing Then
            DTE.StatusBar.Text = "No program is currently being debugged."
            Exit Sub
        End If
    
        Dim ind As Long = StackFrameIndex(DTE.Debugger.CurrentThread.StackFrames, DTE.Debugger.CurrentStackFrame)
        If ind = -1 Then
            DTE.StatusBar.Text = "Stack navigation failed"
            Exit Sub
        End If
    
        ind = ind + aShift
        If ind <= 0 Or ind > DTE.Debugger.CurrentThread.StackFrames.Count Then
            DTE.StatusBar.Text = "Stack frame index is out of range"
            Exit Sub
        End If
    
        DTE.Debugger.CurrentStackFrame = DTE.Debugger.CurrentThread.StackFrames.Item(ind)
        DTE.StatusBar.Text = "Stack frame index: " & ind & " of " & DTE.Debugger.CurrentThread.StackFrames.Count
    End Sub
    
    Sub PreviousStackFrame()
        NavigateStack(1)
    End Sub
    
    Sub NextStackFrame()
        NavigateStack(-1)
    End Sub
    
    0 讨论(0)
  • 2021-02-01 20:34

    I don't think theres an explict next-frame / prev-frame key binding but heres what I do.

    CTRL-ALT-C is already bound to "Debug.CallStack" This will focus you in the Call Stack Tool Window

    Once focused in the Callstack window... Up & Down arrows will move you through the call stack frames

    I've then bound

    CTRL-C, CTRL-S to "DebuggerContextMenus.CallStackWindow.SwitchToFrame" and CTRL-C, CTRL-C to "DebuggerContextMenus.CallStackWindow.SwitchToCode"

    both of which will take you back into the code window at the particular frame.

    Hope that helps.

    0 讨论(0)
  • 2021-02-01 20:41

    Look in Tools->Options->Environment->Keyboard. Enter "stack" or "frame" and related menus will appear. It seems that there's no next and previous call-stack frame.

    0 讨论(0)
  • 2021-02-01 20:47

    I have solved this problem with AutoHotkey. I made this a few months ago. Suppose you wanted to use Control+1 and Control+2 and that Control+Alt+C is bound to showing the Call Stack window:

    ^1::SendInput !^c{down}{enter}
    ^2::SendInput !^c{up}{enter}
    

    It seems to work pretty well. If you aren't already using AutoHotkey to show Visual Studio who's boss, please give it a shot. Your question indicates that you would benefit greatly from it. It's a game changer. Good luck.

    0 讨论(0)
  • 2021-02-01 20:52

    Huge thanks to @Oleg Svechkarenko for his answer that gave me a starting point in crafting this solution. Since modern versions of Visual Studio no longer have official macro support, this should drop in for those who use the Visual Commander plugin, but probably can be easily adapted for any other macro extension.

    Here is the code for the command, I created one for navigating up the call stack and one for navigating down with the same code except the parameter passed to MoveStackIndex(), then bound keyboard shortcuts to them:

    using EnvDTE;
    using EnvDTE80;
    using System;
    
    public class C : VisualCommanderExt.ICommand
    {
        enum MoveDirection
        {
            Up,
            Down,
        }
    
        private bool IsValidFrame(StackFrame frame)
        {
            string language = frame.Language;
    
            bool result = (language == "C#"  || 
                           language == "C++" || 
                           language == "VB"  || 
                           language == "Python");
    
            return result;
        }
    
        private void MoveStackIndex(EnvDTE80.DTE2 DTE, MoveDirection direction)
        {
            StackFrame currentFrame = DTE.Debugger.CurrentStackFrame;
    
            bool foundTarget = false;
            bool pastCurrent = false;
    
            StackFrame lastValid = null;
            foreach (StackFrame frame in DTE.Debugger.CurrentThread.StackFrames)
            {
                bool isCurrent = frame == currentFrame;
    
                if (direction == MoveDirection.Down)
                {
                    if (isCurrent)
                    {
                        if (lastValid == null)
                        {
                            // No valid frames below this one
                            break;
                        }
                        else
                        {
                            DTE.Debugger.CurrentStackFrame = lastValid;
                            foundTarget = true;
                            break;                      
                        }
                    }
                    else
                    {
                        if (IsValidFrame(frame))
                        {
                            lastValid = frame;
                        }
                    }
                }
    
                if (direction == MoveDirection.Up && pastCurrent)
                {
                    if (IsValidFrame(frame))
                    {
                        DTE.Debugger.CurrentStackFrame = frame;
                        foundTarget = true;
                        break;
                    }               
                }
    
                if (isCurrent)
                {
                    pastCurrent = true;
                }
            }
    
            if (!foundTarget)
            {
                DTE.StatusBar.Text = "Failed to find valid stack frame in that direction.";
            }
        }
    
        public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package) 
        {
            if (DTE.Debugger.CurrentProgram == null)
            {
                DTE.StatusBar.Text = "Debug session not active.";
            }
            else
            {
                // NOTE: Change param 2 to MoveDirection.Up for the up command
                MoveStackIndex(DTE, MoveDirection.Down);
            }
        }
    }
    
    0 讨论(0)
提交回复
热议问题